Пройдите по всем подкаталогам и сделайте что-нибудь в сценарии оболочки Unix


17

Я хочу, чтобы мой сценарий оболочки посещал все подкаталоги в главном каталоге. Сделайте что-нибудь в каталогах, отправьте вывод в буферный файл и перейдите к следующему каталогу. Рассмотрим Main Dir = / tmp Sub Dir = ABCD (четыре подкаталога)


2
Хорошо, покажите нам, пожалуйста, ваш сценарий. Какая часть этого доставляет вам неприятности?
Terdon

Ответы:


22

Используйте forцикл:

for d in $(find /path/to/dir -maxdepth 1 -type d)
do
  #Do something, the directory is accessible with $d:
  echo $d
done >output_file

Он ищет только подкаталоги каталога /path/to/dir. Обратите внимание, что простой пример, приведенный выше, потерпит неудачу, если имена каталогов содержат пробелы или специальные символы. Более безопасный подход:

find /tmp -maxdepth 1 -type d -print0 |
  while IFS= read -rd '' dir; do echo "$dir"; done

Или просто bash:

for d in /path/to/dir/*; do
  if [ -d "$d" ]; then
    echo "$d"
  fi
done

(обратите внимание, что в противоположность findэтому также рассматриваются символические ссылки на каталоги и исключаются скрытые)


1
по крайней мере, указать на ограничения и риски, связанные с обработкой результатов, findкак это.
Стефан Шазелас

Привет ... я попытался запустить цикл для d в $ (find / backup / ASHISH -maxdepth 1-type d) do ls -l | awk '{print $ 9}' | grep CC * _ date +"%m%d20%Y"| xargs echo echo $ д
Ашиш

Привет ... Я попробовал ниже для цикла. для d в $ (поиск / резервное копирование / ASHISH -maxdepth 1 -типа d) do ls -l | awk '{print $ 9}' | grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d Ожидаемый результат - ls -ltr из всех подкаталогов , Вышеупомянутая петля не работает
Ашиш

1

Я полный bashновичок, но ветеран UN * X. Хотя, несомненно, это можно сделать в сценариях оболочки Bash, в прежние времена мы привыкли find [-maxdepth <levels>] <start-dir> -exec <command> ;к этому. Вы могли бы сделать man findи поиграть, возможно, пока кто-то не скажет вам, как это сделать в bash!


Я очень польщен тем, что мой "набросок" ответа здесь получил положительное голосование. Однако, почему ответ @chaos ниже получил отрицательное голосование? (Как новичок на этой доске, я не могу публиковать этот комментарий против его ответа, только против моего собственного.) Его второе предложение верно для решения сценария оболочки и позволяет избежать накладных расходов при выполнении внешней findкоманды.
JonBrave

Его второе действительно правильно. Его первый сбой, если имена каталогов содержат пробелы или специальные символы (обратная косая черта, например). См. Правку, которую я внес в его ответ, для безопасной версии.
Terdon

Я согласен. Это был его второй, единственный ответ, который я хвалил.
JonBrave

Я знаю, я только что объяснил понижающий голос (который я не бросил).
Terdon


1

Похоже, вы хотите имена файлов под каждым из подкаталогов; что ls -l | awkнедостаточно надежно, для чего, если эти имена файлов содержат пробелы и / или символы новой строки? Нижеследующее findбудет работать даже для findтех, у кого не получилось -maxdepth:

find . ! -name . -type d -prune -exec sh -c '
   cd "$1" && \
   find "." ! -name . -prune  -type f
' {} {} \;

0

Я получил решение. Команда find ниже отвечает моим требованиям.

find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && ls -l |awk '{ print $9 }' |grep `date +"%m%d%Y"`|xargs echo" \;

0

Также возможно использование ls, grep и tr

for dir in $(ls -1FA | grep / | tr -d /); do echo $dir/something; done

ls -1FA | grep / | tr -d / | while IFS= read -r TD; do echo $TD/something; done

du / sed также может быть использован как селектор, если у вашего ls нет вышеупомянутых опций

du --max-depth=1 | sed -e 's/^.*\.\///' | grep -v '\.$'

Может быть важно отметить, что эти примеры возвращают скрытые каталоги и исключают родительские и текущие каталоги


1
(1)  lsзаписывает по одному файлу на строку (что -1указывает опция) по умолчанию, когда стандартный вывод представляет собой канал (так что это лишнее в ваших ответах). (2) Анализ выходных данных lsявляется плохой идеей - посмотрите на это и на это . Ваш первый ответ потерпит неудачу, если в именах каталогов есть пробелы (или новые строки), и все они потерпят неудачу, если в их именах будут новые строки. (3) Вы должны всегда заключать в кавычки переменные оболочки (например, "$dir"), если у вас нет веских причин не делать этого, и вы уверены, что знаете, что делаете.
Скотт

Хорошие очки Скотт. Оставляя ответ как, для многих систем без вопиюще названных dirs, я думаю, что он все еще может быть полезен для одного.
JGurtz
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.