Найдите название подкаталогов и файлы процесса в каждом

Скажем /tmp имеет подкаталоги /test1, /test2, /test3 и так далее, и у каждого есть несколько файлов внутри.

Я должен запустить while петля или for цикл, чтобы найти имя каталогов (в этом случае /test1, /test2,...) и запустите команду, которая обрабатывает все файлы внутри каждого каталога.

Так, например, я должен получить имена каталогов в /tmp которые будут test1, test2... Для каждого подкаталога мне нужно обработать файлы внутри него.

Как я могу это сделать?


Разъяснение:

Это команда, которую я хочу выполнить:

find /PROD/140725_D0/ -name "*.json" -exec /tmp/test.py {} \;

где 140725_D0 пример одного подкаталога для обработки - есть несколько магазинов с разными именами.

Итак, используя for или же while цикл, я хочу найти все подкаталоги и запустить команду для файлов в каждом.

for или же while цикл должен итеративно заменять жестко закодированное имя 140725_D0 в команде поиска выше.

5 ответов

Решение

Вы должны быть в состоянии сделать с одним find команда со встроенной командой оболочки:

find /PROD -type d -execdir sh -c 'for f in *.json; do /tmp/test.py "$f"; done' \;

Замечания: -execdir не совместим с POSIX, но версии BSD (OSX) и GNU (Linux) find поддержать это; ниже смотрите альтернативу POSIX.

  • Подход состоит в том, чтобы find сопоставить каталоги, а затем в каждом сопоставленном каталоге выполнить оболочку с циклом обработки файлов (sh -c '<shellCmd>').
  • Если не все подкаталоги гарантированно имеют *.json файлы, измените команду оболочки на for f in *.json; do [ -f "$f" ] && /tmp/test.py "$f"; done

Обновление: еще два соображения; Кончик шляпы к ответу Кенорба:

  • По умолчанию, find обрабатывает все поддерево входного каталога. Чтобы ограничить соответствие непосредственными подкаталогами, используйте -maxdepth 1 [1]:

    find /PROD -maxdepth 1 -type d ...
    
  • Как указано, -execdir - который запускает команду, переданную ему в каталоге, обрабатываемом в данный момент - не совместим с POSIX; Вы можете обойти это, используя -exec вместо этого и путем включения cd команда с указанием пути к каталогу ({}) в команде оболочки:

    find /PROD -type d -exec sh -c 'cd "{}" && for f in *.json; do /tmp/test.py "$f"; done' \;
    

[1] Строго говоря, вы можете разместить -maxdepth вариант в любом месте после пути входного файла на find командная строка - как опция, она не позиционная. Тем не менее, GNU find выдаст предупреждение, если вы не разместите его перед тестами (например, -type ) и действия (такие как -exec ).

Попробуйте следующее использование find:

find . -type d -exec sh -c 'cd "{}" && echo Do some stuff for {}, files are: $(ls *.*)' ';'

использование -maxdepth если вы хотите ограничить уровни каталогов.

Другое решение - немного изменить код Python внутри вашего скрипта, чтобы принимать и обрабатывать несколько файлов. Например, если ваш скрипт содержит что-то вроде:

def process(fname):
    print 'Processing file', fname

if __name__ == '__main__':
    import sys
    process(sys.argv[1])

Вы можете заменить последнюю строку на:

    for fname in sys.argv[1:]:
        process(fname)

После этой простой модификации вы можете назвать свой скрипт следующим образом:

/tmp/test.py /PROD/*/*.json

и пусть он обрабатывает все нужные файлы JSON.

Вы можете сделать это, используя функцию подоболочки bash:

for i in /tmp/test*; do
  # don't do anything if there's no /test directory in /tmp
  [ "$i" != "/tmp/test*" ] || continue

  for j in $i/*.json; do
    # don't do anything if there's nothing to run
    [ "$j" != "$i/*.json" ] || continue

    (cd $i && ./file_to_run)
  done
done

Когда вы заключаете команду в ( а также ) он запускает подоболочку для запуска команды. Подоболочка похожа на запуск другого экземпляра bash, за исключением того, что она немного более оптимальна.

Вы также можете просто попросить оболочку развернуть нужные вам каталоги / файлы, например, используя команду xargs:

echo /PROD/*/*.json | xargs -n 1 /tmp/test.py

или даже используя свой оригинал find команда:

find /PROD/* -name "*.json" -exec /tmp/test.py {} \;

Обе команды будут обрабатывать все файлы JSON, содержащиеся в любом подкаталоге /PROD,

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