Как отделить командный вывод к отдельным строкам

Вы можете уменьшить использование ОЗУ, остановив ненужные службы. Используйте service --status-all, чтобы просмотреть статус всех служб и sudo stop <servicename>, чтобы временно остановить службу. Вы можете удалить упакованную постоянную покупку, используя sudo apt-get remove <packagename>

8
задан 2 November 2017 в 15:45

12 ответов

Если вывод команды содержит несколько строк, тогда цитируйте свои переменные, чтобы сохранить эти символы новой строки при повторении:

echo "$list"

В противном случае оболочка будет расширять и разбивать содержимое переменной на пробелы (пробелы, новые строки, вкладки), и они будут потеряны.

9
ответ дан 22 May 2018 в 16:52

Если вывод команды содержит несколько строк, тогда цитируйте свои переменные, чтобы сохранить эти символы новой строки при повторении:

echo "$list"

В противном случае оболочка будет расширять и разбивать содержимое переменной на пробелы (пробелы, новые строки, вкладки), и они будут потеряны.

9
ответ дан 18 July 2018 в 04:03

Если вывод команды содержит несколько строк, тогда цитируйте свои переменные, чтобы сохранить эти символы новой строки при повторении:

echo "$list"

В противном случае оболочка будет расширять и разбивать содержимое переменной на пробелы (пробелы, новые строки, вкладки), и они будут потеряны.

9
ответ дан 24 July 2018 в 17:59

Вместо ненадлежащего ввода функции ls в переменную, а затем echo, которая удаляет все цвета, используйте

ls -a1

Из man ls

[ f2]

Я не советую вам делать что-либо с выходом ls, кроме отображения его:)

Используйте, например, shell globs и цикл for, чтобы что-то сделать с файлы ...

shopt -s dotglob                  # to include hidden files*

for i in R/*; do echo "$i"; done

* это не будет включать текущий каталог . или его родительский .., хотя

13
ответ дан 22 May 2018 в 16:52
  • 1
    Я бы рекомендовал заменить: echo "$i" на printf "%s\n" "$i" (чтобы никто не задохнулся, если имя файла начинается с " - "). Фактически большую часть времени echo something следует заменить на printf "%s\n" "something". – Olivier Dulac 3 November 2017 в 13:56
  • 2
    @OlivierDulac Они все начинаются с R здесь, но в целом, да. Однако даже для сценариев попытка всегда размещать ведущие - в путях вызывает проблемы: люди принимают --, которые поддерживают только некоторые команды, означает конец опций. Я видел find . [tests] -exec [cmd] -- {} \;, где [cmd] не поддерживает --. Каждый путь начинается с . в любом случае! Но это не аргумент против замены echo на printf '%s\n'. Здесь можно заменить весь цикл на printf '%s\n' R/*. У Bash есть printf как встроенный, поэтому фактически нет предела количеству / длине аргументов. – Eliah Kagan 3 November 2017 в 14:34

Положив его в кавычки, как предложил @muru, действительно сделает то, о чем вы просили, вы также можете рассмотреть возможность использования массива для этого. Например:

IFS=$'\n' dirs=( $(find . -type d) )

IFS=$'\n' сообщает bash, что только разделяет вывод на символах новой строки o получает каждый элемент массива. Без него он будет разбиваться на пробелы, поэтому a file name with spaces.txt будет состоять из 5 отдельных элементов вместо одного. Этот подход будет нарушен, если ваши имена файлов / каталогов могут содержать новые строки (\n). Он сохранит каждую строку вывода команды как элемент массива.

Обратите внимание, что я также изменил старый стиль `command` на $(command), который является предпочтительным синтаксисом.

Теперь у вас есть массив под названием $dirs, каждый из которых имеет элементы является строкой вывода предыдущей команды. Например:

$ find . -type d
.
./olad
./ho
./ha
./ads
./bar
./ga
./da
$ IFS=$'\n' dirs=( $(find . -type d) )
$ for d in "${dirs[@]}"; do
    echo "DIR: $d"
  done
DIR: .
DIR: ./olad
DIR: ./ho
DIR: ./ha
DIR: ./ads
DIR: ./bar
DIR: ./ga
DIR: ./da

Теперь из-за некоторой странности в bash (см. , предложенный ), после этого вам нужно будет сбросить IFS до исходного значения. Итак, сохраните его и заново:

oldIFS="$IFS"
IFS=$'\n' dirs=( $(find . -type d) ) 
IFS="$oldIFS"

Или сделайте это вручную:

IFS=" "$'\t\n '

В качестве альтернативы просто закройте текущий терминал. У вашего нового будет оригинальная настройка IFS.

9
ответ дан 22 May 2018 в 16:52
  • 1
    Я мог бы предложить что-то подобное, но тогда часть du заставляет его смотреть, что OP больше заинтересован в сохранении выходного формата. – muru 2 November 2017 в 19:23
  • 2
    Как я могу сделать эту работу, если имена каталогов содержат пробелы? – dessert 2 November 2017 в 19:37
  • 3
    @dessert кричит! Теперь он должен работать с пробелами (но не с символами новой строки). Спасибо, что указали это. – terdon♦ 2 November 2017 в 20:20
  • 4
    Обратите внимание, что после этого назначения массива следует сбросить или отключить IFS. unix.stackexchange.com/q/264635/70524 – muru 2 November 2017 в 21:11
  • 5
    @muru oh wow, спасибо, я забыл об этой странности. – terdon♦ 2 November 2017 в 22:02

если вы должны магазин выход и вы хотите массив, [ф12] легко.

во-первых, рассмотреть, если вы должны магазин выход своей команды на все. Если нет, то просто выполните команду.

если вы решили, что хотите прочитать вывод команды как массив строк, это правда, что один из способов сделать это, чтобы отключить подстановку, установите [от f13] для разделения по линиям, использовать подстановку команд внутри [ф14] [ф15] массива синтаксис создания и сброса [ф16] после этого, который является более сложным, чем кажется. ответ terdon охватывает некоторые из этого подхода. Но я предлагаю вам использовать [f17 в], оболочки bash встроенная команда для чтения текст как массив строк, а не. Вот простой случай, когда вы читаете из файла:

[Ф1]

это читает строки в массив называется [ф18]. Без сложнее [зг19], вы будет читать из стандартного ввода оболочки (обычно стержень), а не файл, названный нужно. Читать в массив по умолчанию [клавиши f21], передать ее имя. Например, эта функция считывает в массив [ф22]:

[Ф2]

другое поведение по умолчанию можно изменить, что стандартный ввод в конце строки остаются на месте, они появляются в качестве последнего символа в каждый элемент массива (если вклад закончился без символа новой строки, в этом случае последний элемент не имеет). Чтобы грызть эти строки, чтобы они не появляются в массиве, передать параметр [ф23] для [ф24]. Например, эта функция считывает в массив [f25 привод датчика] и не писать конечные символы новой строки на элементы массива:

[Ф3]

Вы можете также использовать [ф26] без передача имени массива, то есть работает с неявным имя массива MAPFILE тоже.

в [ф28] раковина встроенная поддержка других вариантов, и он может также использоваться в качестве readarray. Запустить [f30 С] (и [ф31]) для деталей.

[dиода d17]но я предлагаю вам использовать [f17 в], оболочки bash встроенная команда для чтения текст как массив строк, а не. для достижения, что использование заместительной процесс. Эта команда считывает строки из командной [f32 из] с arguments... в качестве аргументов командной строки и мест в них в mapfile по умолчанию для массива [ф35], с их прекращения символы новой строки удаляются:[!dиода d17] [Ф4]

процесс замещения заменяет [f36 в] с реальным именем, из которой выход работает [фунции f37] можно прочитать. Файл процесс замещения, а не terdon ответ и, в Ubuntu, это будет называться как /dev/fd/63 (иногда с какой-то другой номер, чем [ф39]), но вам не нужно беспокоиться о деталях, потому что оболочка позаботится обо всем этом за кадром.

вы думаете вы могли бы отказаться от замещения процесс, используя вместо [ф40], но это не работает, потому что, когда у тебя конвейер из нескольких команд, разделенных [ф41], Баш запускается работает все команды в подоболочек. Таким образом, оба some-command arguments... и mapfile -t работать в своей среде, инициализируется, но, обособленное от среды оболочки, в которой вы запустите производство. В том случае, когда где [пулемет f44] работает [f45 с] массив заполнен, но потом этот массив удаляется, когда команда заканчивается. MAPFILE никогда не созданное или модифицированное для абонента.

вот как пример в ответ terdon выглядит, в целом, если вы используете mapfile:

[ф5] [ф6]

Вот именно. Вам не надо ответ terdon это!d33], его значение, установить его на символ новой строки, затем сбросить или повторно сбросить его позже. Вы не должны отключить подстановка (например, с set -f) - которые действительно необходимы, если вы хотите использовать этот метод всерьез, так как имена файлов могут содержать [ф50], ?, и [--снова включите его (set +f) потом.

Вы можете заменить этот конкретный цикл целиком с одного printf команды-хотя это на самом деле не благо [f55, которая, как вы можете сделать это ли вы использовать mapfile или другой метод для заполнения массива. Вот краткая версия:

[ф7]

важно иметь в виду, что, как подстановка - , Операционная построчно не всегда уместна, и не будет работать с именами файлов, которые содержат символы новой строки. Я рекомендую против именования файлов, но это [f32 из] произошло, в том числе случайно.

[dрайвер d41]на самом деле там нет один-размер-подходит-всем решение.[!dрайвер d41]

вы просили "универсальную команду для всех сценариев", и подход с использованием mapfile несколько подходов к этой цели, но я призываю вас пересмотреть ваши требования.

[d43 см.]задачи показано выше лучше достигнута с помощью всего одного find команда:[!d43 см.] [ф8]

Вы также можете использовать внешнюю команду, как sed, чтобы добавить [от f60] в начале каждой строки. Это, возможно, несколько коряво, и в отличие от что найти команду, это добавит дополнительной "приставки" в имена файлов, содержащие символы новой строки, но он работает независимо от его входа, так что он вроде отвечает Вашим требованиям, а это все же предпочтительнее, чем чтение вывода в переменную или массив:

[F9] и

если вам нужно перечислить и проанализировать действия каждого каталога, такие как бег и это еще предпочтительнее, чем чтение вывода в переменную или массив и, пройдя путь каталога в качестве аргумента, find позволяет сделать это:[!возвращение д46] [ф10]

в качестве другого примера, давайте на общие задачи добавление префикса для каждой линии. Предположим, я хочу увидеть результат help mapfile, но количество авш линии. Я бы не стал вообще использовать [64-го фокуса] для этого, ни любой другой метод, который читает его в переменной оболочки или оболочки массива. Предположим, что [камера f65] не дает форматирование, я хочу, я могу использовать awk:

[ф11]

вот как пример не только вы должны справиться с дополнительной сложностью, используя свои оболочки, когда существующая команда или комбинация действующих команд может уже делать то, что вам нужно, как хорошо или лучше, но весь вывод команды должен быть сохранен в памяти. Иногда вы, возможно, знаете, что не является проблемой, но иногда вы можете быть обработки больших файлов.

альтернатива, который обычно пытался ... и иногда все сделано правильно-это читать ввод построчно с read -r в цикле. Если вам не нужно хранить предыдущие линии при работе на более поздних линий, и вы должны использовать длинные ввода, то это может быть лучше, чем [f68 не]. Но его тоже следует избегать в тех случаях, когда вы можете просто вставьте его в команду, которая может сделать работу, которая в большинстве случаев.

0
ответ дан 22 May 2018 в 16:52

если вы должны магазин выход и вы хотите массив, mapfile легко.

во-первых, рассмотреть, если вы должны магазин выход своей команды на все. Если нет, то просто выполните команду.

если вы решили, что хотите прочитать вывод команды как массив строк, это правда, что один из способов сделать это, чтобы отключить подстановку, установите [от f13] для разделения по линиям, использовать подстановку команд внутри ( ) массива синтаксис создания и сброса IFS после этого, который является более сложным, чем кажется. ответ terdon охватывает некоторые из этого подхода. Но я предлагаю вам использовать [f17 в], оболочки bash встроенная команда для чтения текст как массив строк, а не. Вот простой случай, когда вы читаете из файла:

mapfile < filename

это читает строки в массив называется MAPFILE. Без сложнее [зг19], вы будет читать из стандартного ввода оболочки (обычно стержень), а не файл, названный нужно. Читать в массив по умолчанию [клавиши f21], передать ее имя. Например, эта функция считывает в массив lines:

mapfile lines < filename

другое поведение по умолчанию можно изменить, что стандартный ввод в конце строки остаются на месте, они появляются в качестве последнего символа в каждый элемент массива (если вклад закончился без символа новой строки, в этом случае последний элемент не имеет). Чтобы грызть эти строки, чтобы они не появляются в массиве, передать параметр -t для mapfile. Например, эта функция считывает в массив [f25 привод датчика] и не писать конечные символы новой строки на элементы массива:

mapfile -t records < filename

Вы можете также использовать -t без передача имени массива, то есть работает с неявным имя массива MAPFILE тоже.

в mapfile раковина встроенная поддержка других вариантов, и он может также использоваться в качестве readarray. Запустить [f30 С] (и help readarray) для деталей.

[dиода d17]но я предлагаю вам использовать [f17 в], оболочки bash встроенная команда для чтения текст как массив строк, а не. для достижения, что использование заместительной процесс. Эта команда считывает строки из командной [f32 из] с arguments... в качестве аргументов командной строки и мест в них в mapfile по умолчанию для массива MAPFILE, с их прекращения символы новой строки удаляются:[!dиода d17] mapfile -t < <(some-command arguments...)

процесс замещения заменяет [f36 в] с реальным именем, из которой выход работает [fунции f37] можно прочитать. Файл процесс замещения, а не terdon ответ и, в Ubuntu, это будет называться как /dev/fd/63 (иногда с какой-то другой номер, чем 63), но вам не нужно беспокоиться о деталях, потому что оболочка позаботится обо всем этом за кадром.

вы думаете вы могли бы отказаться от замещения процесс, используя вместо some-command arguments... | mapfile -t, но это не работает, потому что, когда у тебя конвейер из нескольких команд, разделенных |, Баш запускается работает все команды в подоболочек. Таким образом, оба some-command arguments... и mapfile -t работать в своей среде, инициализируется, но, обособленное от среды оболочки, в которой вы запустите производство. В том случае, когда где [пулемет f44] работает [f45 с] массив заполнен, но потом этот массив удаляется, когда команда заканчивается. MAPFILE никогда не созданное или модифицированное для абонента.

вот как пример в ответ terdon выглядит, в целом, если вы используете mapfile:

mapfile -t dirs < <(find . -type d) for d in "${dirs[@]}"; do echo "DIR: $d" done

Вот именно. Вам не надо ответ terdon это!d33], его значение, установить его на символ новой строки, затем сбросить или повторно сбросить его позже. Вы не должны отключить подстановка (например, с set -f) - которые действительно необходимы, если вы хотите использовать этот метод всерьез, так как имена файлов могут содержать *, ?, и [--снова включите его (set +f) потом.

Вы можете заменить этот конкретный цикл целиком с одного printf команды-хотя это на самом деле не благо [f55, которая, как вы можете сделать это ли вы использовать mapfile или другой метод для заполнения массива. Вот краткая версия:

mapfile -t < <(find . -type d) printf 'DIR: %s\n' "${MAPFILE[@]}"

важно иметь в виду, что, как подстановка - , Операционная построчно не всегда уместна, и не будет работать с именами файлов, которые содержат символы новой строки. Я рекомендую против именования файлов, но это [f32 из] произошло, в том числе случайно.

[dрайвер d41]на самом деле там нет один-размер-подходит-всем решение.[!dрайвер d41]

вы просили "универсальную команду для всех сценариев", и подход с использованием mapfile несколько подходов к этой цели, но я призываю вас пересмотреть ваши требования.

[d43 см.]задачи показано выше лучше достигнута с помощью всего одного find команда:[!d43 см.] find . -type d -printf 'DIR: %p\n'

Вы также можете использовать внешнюю команду, как sed, чтобы добавить [от f60] в начале каждой строки. Это, возможно, несколько коряво, и в отличие от что найти команду, это добавит дополнительной "приставки" в имена файлов, содержащие символы новой строки, но он работает независимо от его входа, так что он вроде отвечает Вашим требованиям, а это все же предпочтительнее, чем чтение вывода в переменную или массив:

[F9] и

если вам нужно перечислить и проанализировать действия каждого каталога, такие как бег и это еще предпочтительнее, чем чтение вывода в переменную или массив и, пройдя путь каталога в качестве аргумента, find позволяет сделать это:[!возвращение д46] find . -type d -print -exec some-command {} \;

в качестве другого примера, давайте на общие задачи добавление префикса для каждой линии. Предположим, я хочу увидеть результат help mapfile, но количество авш линии. Я бы не стал вообще использовать [64-го фокуса] для этого, ни любой другой метод, который читает его в переменной оболочки или оболочки массива. Предположим, что [камера f65] не дает форматирование, я хочу, я могу использовать awk:

help mapfile | awk '{ printf "%3d: %s\n", NR, $0 }'

вот как пример не только вы должны справиться с дополнительной сложностью, используя свои оболочки, когда существующая команда или комбинация действующих команд может уже делать то, что вам нужно, как хорошо или лучше, но весь вывод команды должен быть сохранен в памяти. Иногда вы, возможно, знаете, что не является проблемой, но иногда вы можете быть обработки больших файлов.

альтернатива, который обычно пытался ... и иногда все сделано правильно-это читать ввод построчно с read -r в цикле. Если вам не нужно хранить предыдущие линии при работе на более поздних линий, и вы должны использовать длинные ввода, то это может быть лучше, чем [f68 не]. Но его тоже следует избегать в тех случаях, когда вы можете просто вставьте его в команду, которая может сделать работу, которая в большинстве случаев.

0
ответ дан 18 July 2018 в 04:03

Положив его в кавычки, как предложил @muru, действительно сделает то, о чем вы просили, вы также можете рассмотреть возможность использования массива для этого. Например:

IFS=$'\n' dirs=( $(find . -type d) )

IFS=$'\n' сообщает bash, что только разделяет вывод на символах новой строки o получает каждый элемент массива. Без него он будет разбиваться на пробелы, поэтому a file name with spaces.txt будет состоять из 5 отдельных элементов вместо одного. Этот подход будет нарушен, если ваши имена файлов / каталогов могут содержать новые строки (\n). Он сохранит каждую строку вывода команды как элемент массива.

Обратите внимание, что я также изменил старый стиль `command` на $(command), который является предпочтительным синтаксисом.

Теперь у вас есть массив под названием $dirs, каждый из которых имеет элементы является строкой вывода предыдущей команды. Например:

$ find . -type d . ./olad ./ho ./ha ./ads ./bar ./ga ./da $ IFS=$'\n' dirs=( $(find . -type d) ) $ for d in "${dirs[@]}"; do echo "DIR: $d" done DIR: . DIR: ./olad DIR: ./ho DIR: ./ha DIR: ./ads DIR: ./bar DIR: ./ga DIR: ./da

Теперь из-за некоторой странности в bash (см. [D1], предложенный ), после этого вам нужно будет сбросить IFS до исходного значения. Итак, сохраните его и заново:

oldIFS="$IFS" IFS=$'\n' dirs=( $(find . -type d) ) IFS="$oldIFS"

Или сделайте это вручную:

IFS=" "$'\t\n '

В качестве альтернативы просто закройте текущий терминал. У вашего нового будет оригинальная настройка IFS.

9
ответ дан 18 July 2018 в 04:03

Вместо ненадлежащего ввода функции ls в переменную, а затем echo, которая удаляет все цвета, используйте

ls -a1

Из man ls

-1 list one file per line. Avoid '\n' with -q or -b

Я не советую вам делать что-либо с выходом ls, кроме отображения его:)

Используйте, например, shell globs и цикл for, чтобы что-то сделать с файлы ...

shopt -s dotglob # to include hidden files* for i in R/*; do echo "$i"; done

* это не будет включать текущий каталог . или его родительский .., хотя

13
ответ дан 18 July 2018 в 04:03

если вы должны магазин выход и вы хотите массив, mapfile легко.

во-первых, рассмотреть, если вы должны магазин выход своей команды на все. Если нет, то просто выполните команду.

если вы решили, что хотите прочитать вывод команды как массив строк, это правда, что один из способов сделать это, чтобы отключить подстановку, установите [от f13] для разделения по линиям, использовать подстановку команд внутри ( ) массива синтаксис создания и сброса IFS после этого, который является более сложным, чем кажется. ответ terdon охватывает некоторые из этого подхода. Но я предлагаю вам использовать [f17 в], оболочки bash встроенная команда для чтения текст как массив строк, а не. Вот простой случай, когда вы читаете из файла:

mapfile < filename

это читает строки в массив называется MAPFILE. Без сложнее [зг19], вы будет читать из стандартного ввода оболочки (обычно стержень), а не файл, названный нужно. Читать в массив по умолчанию [клавиши f21], передать ее имя. Например, эта функция считывает в массив lines:

mapfile lines < filename

другое поведение по умолчанию можно изменить, что стандартный ввод в конце строки остаются на месте, они появляются в качестве последнего символа в каждый элемент массива (если вклад закончился без символа новой строки, в этом случае последний элемент не имеет). Чтобы грызть эти строки, чтобы они не появляются в массиве, передать параметр -t для mapfile. Например, эта функция считывает в массив [f25 привод датчика] и не писать конечные символы новой строки на элементы массива:

mapfile -t records < filename

Вы можете также использовать -t без передача имени массива, то есть работает с неявным имя массива MAPFILE тоже.

в mapfile раковина встроенная поддержка других вариантов, и он может также использоваться в качестве readarray. Запустить [f30 С] (и help readarray) для деталей.

[dиода d17]но я предлагаю вам использовать [f17 в], оболочки bash встроенная команда для чтения текст как массив строк, а не. для достижения, что использование заместительной процесс. Эта команда считывает строки из командной [f32 из] с arguments... в качестве аргументов командной строки и мест в них в mapfile по умолчанию для массива MAPFILE, с их прекращения символы новой строки удаляются:[!dиода d17] mapfile -t < <(some-command arguments...)

процесс замещения заменяет [f36 в] с реальным именем, из которой выход работает [fунции f37] можно прочитать. Файл процесс замещения, а не terdon ответ и, в Ubuntu, это будет называться как /dev/fd/63 (иногда с какой-то другой номер, чем 63), но вам не нужно беспокоиться о деталях, потому что оболочка позаботится обо всем этом за кадром.

вы думаете вы могли бы отказаться от замещения процесс, используя вместо some-command arguments... | mapfile -t, но это не работает, потому что, когда у тебя конвейер из нескольких команд, разделенных |, Баш запускается работает все команды в подоболочек. Таким образом, оба some-command arguments... и mapfile -t работать в своей среде, инициализируется, но, обособленное от среды оболочки, в которой вы запустите производство. В том случае, когда где [пулемет f44] работает [f45 с] массив заполнен, но потом этот массив удаляется, когда команда заканчивается. MAPFILE никогда не созданное или модифицированное для абонента.

вот как пример в ответ terdon выглядит, в целом, если вы используете mapfile:

mapfile -t dirs < <(find . -type d) for d in "${dirs[@]}"; do echo "DIR: $d" done

Вот именно. Вам не надо ответ terdon это!d33], его значение, установить его на символ новой строки, затем сбросить или повторно сбросить его позже. Вы не должны отключить подстановка (например, с set -f) - которые действительно необходимы, если вы хотите использовать этот метод всерьез, так как имена файлов могут содержать *, ?, и [--снова включите его (set +f) потом.

Вы можете заменить этот конкретный цикл целиком с одного printf команды-хотя это на самом деле не благо [f55, которая, как вы можете сделать это ли вы использовать mapfile или другой метод для заполнения массива. Вот краткая версия:

mapfile -t < <(find . -type d) printf 'DIR: %s\n' "${MAPFILE[@]}"

важно иметь в виду, что, как подстановка - , Операционная построчно не всегда уместна, и не будет работать с именами файлов, которые содержат символы новой строки. Я рекомендую против именования файлов, но это [f32 из] произошло, в том числе случайно.

[dрайвер d41]на самом деле там нет один-размер-подходит-всем решение.[!dрайвер d41]

вы просили "универсальную команду для всех сценариев", и подход с использованием mapfile несколько подходов к этой цели, но я призываю вас пересмотреть ваши требования.

[d43 см.]задачи показано выше лучше достигнута с помощью всего одного find команда:[!d43 см.] find . -type d -printf 'DIR: %p\n'

Вы также можете использовать внешнюю команду, как sed, чтобы добавить [от f60] в начале каждой строки. Это, возможно, несколько коряво, и в отличие от что найти команду, это добавит дополнительной "приставки" в имена файлов, содержащие символы новой строки, но он работает независимо от его входа, так что он вроде отвечает Вашим требованиям, а это все же предпочтительнее, чем чтение вывода в переменную или массив:

[F9] и

если вам нужно перечислить и проанализировать действия каждого каталога, такие как бег и это еще предпочтительнее, чем чтение вывода в переменную или массив и, пройдя путь каталога в качестве аргумента, find позволяет сделать это:[!возвращение д46] find . -type d -print -exec some-command {} \;

в качестве другого примера, давайте на общие задачи добавление префикса для каждой линии. Предположим, я хочу увидеть результат help mapfile, но количество авш линии. Я бы не стал вообще использовать [64-го фокуса] для этого, ни любой другой метод, который читает его в переменной оболочки или оболочки массива. Предположим, что [камера f65] не дает форматирование, я хочу, я могу использовать awk:

help mapfile | awk '{ printf "%3d: %s\n", NR, $0 }'

вот как пример не только вы должны справиться с дополнительной сложностью, используя свои оболочки, когда существующая команда или комбинация действующих команд может уже делать то, что вам нужно, как хорошо или лучше, но весь вывод команды должен быть сохранен в памяти. Иногда вы, возможно, знаете, что не является проблемой, но иногда вы можете быть обработки больших файлов.

альтернатива, который обычно пытался ... и иногда все сделано правильно-это читать ввод построчно с read -r в цикле. Если вам не нужно хранить предыдущие линии при работе на более поздних линий, и вы должны использовать длинные ввода, то это может быть лучше, чем [f68 не]. Но его тоже следует избегать в тех случаях, когда вы можете просто вставьте его в команду, которая может сделать работу, которая в большинстве случаев.

0
ответ дан 24 July 2018 в 17:59

Положив его в кавычки, как предложил @muru, действительно сделает то, о чем вы просили, вы также можете рассмотреть возможность использования массива для этого. Например:

IFS=$'\n' dirs=( $(find . -type d) )

IFS=$'\n' сообщает bash, что только разделяет вывод на символах новой строки o получает каждый элемент массива. Без него он будет разбиваться на пробелы, поэтому a file name with spaces.txt будет состоять из 5 отдельных элементов вместо одного. Этот подход будет нарушен, если ваши имена файлов / каталогов могут содержать новые строки (\n). Он сохранит каждую строку вывода команды как элемент массива.

Обратите внимание, что я также изменил старый стиль `command` на $(command), который является предпочтительным синтаксисом.

Теперь у вас есть массив под названием $dirs, каждый из которых имеет элементы является строкой вывода предыдущей команды. Например:

$ find . -type d . ./olad ./ho ./ha ./ads ./bar ./ga ./da $ IFS=$'\n' dirs=( $(find . -type d) ) $ for d in "${dirs[@]}"; do echo "DIR: $d" done DIR: . DIR: ./olad DIR: ./ho DIR: ./ha DIR: ./ads DIR: ./bar DIR: ./ga DIR: ./da

Теперь из-за некоторой странности в bash (см. [D1], предложенный ), после этого вам нужно будет сбросить IFS до исходного значения. Итак, сохраните его и заново:

oldIFS="$IFS" IFS=$'\n' dirs=( $(find . -type d) ) IFS="$oldIFS"

Или сделайте это вручную:

IFS=" "$'\t\n '

В качестве альтернативы просто закройте текущий терминал. У вашего нового будет оригинальная настройка IFS.

9
ответ дан 24 July 2018 в 17:59
  • 1
    Я мог бы предложить что-то подобное, но тогда часть du заставляет его смотреть, что OP больше заинтересован в сохранении выходного формата. – muru 2 November 2017 в 19:23
  • 2
    Как я могу сделать эту работу, если имена каталогов содержат пробелы? – dessert 2 November 2017 в 19:37
  • 3
    @dessert кричит! Теперь он должен работать с пробелами (но не с символами новой строки). Спасибо, что указали это. – terdon♦ 2 November 2017 в 20:20
  • 4
    Обратите внимание, что после этого назначения массива следует сбросить или отключить IFS. [D0] unix.stackexchange.com/q/264635/70524 – muru 2 November 2017 в 21:11
  • 5
    @muru oh wow, спасибо, я забыл об этой странности. – terdon♦ 2 November 2017 в 22:02

Вместо ненадлежащего ввода функции ls в переменную, а затем echo, которая удаляет все цвета, используйте

ls -a1

Из man ls

-1 list one file per line. Avoid '\n' with -q or -b

Я не советую вам делать что-либо с выходом ls, кроме отображения его:)

Используйте, например, shell globs и цикл for, чтобы что-то сделать с файлы ...

shopt -s dotglob # to include hidden files* for i in R/*; do echo "$i"; done

* это не будет включать текущий каталог . или его родительский .., хотя

13
ответ дан 24 July 2018 в 17:59
  • 1
    Я бы рекомендовал заменить: echo "$i" на printf "%s\n" "$i" (чтобы никто не задохнулся, если имя файла начинается с & quot; - & quot;). Фактически большую часть времени echo something следует заменить на printf "%s\n" "something". – Olivier Dulac 3 November 2017 в 13:56
  • 2
    @OlivierDulac Они все начинаются с R здесь, но в целом, да. Однако даже для сценариев попытка всегда размещать ведущие - в путях вызывает проблемы: люди принимают --, которые поддерживают только некоторые команды, означает конец опций. Я видел find . [tests] -exec [cmd] -- {} \;, где [cmd] не поддерживает --. Каждый путь начинается с . в любом случае! Но это не аргумент против замены echo на printf '%s\n'. Здесь можно заменить весь цикл на printf '%s\n' R/*. У Bash есть printf как встроенный, поэтому фактически нет предела количеству / длине аргументов. – Eliah Kagan 3 November 2017 в 14:34

Другие вопросы по тегам:

Похожие вопросы: