Используя awk с find -exec

У меня есть структура каталогов с 14 каталогами, содержащими кучу файлов, содержащих данные в формате трех столбцов (разделенных вкладками). Я намеревался использовать find и awk, чтобы извлечь второй столбец из каждого из этих файлов и вывести его с тем же именем файла, но в другой корневой папке. Вот набросок моего каталога.

data / all -> AA, AB, AC, AD... (A * - это папки, содержащие файлы с данными, сохраненными в формате с тремя столбцами, например, AA100.txt, AA101.txt ...)

Я хочу, чтобы измененные (с одним столбцом) файлы с тем же именем, но все в новом корневом каталоге data/pos (в отличие от data/all/) -> AA, AB, AC, AD ... (снова каждый из которых содержит A*100.txt, A*101...)

Я попытался использовать find -exec и дать ему команду awk, но у меня проблемы с выводом файла в нужное место.

когда в данных / все /

find * -type f -exec awk '{print $ 2}' '{}'>../ pos / '{}' \;

Однако {} как подстановочный знак для входного файла, кажется, не работает при выводе файла?

Что я делаю неправильно? (Я на сервере Ubuntu, кстати)

3 ответа

Решение

Вы можете попробовать без поиска, если все, что вы хотите, это все файлы. Пока в data/all/запустите это:

for file in ./*; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done

Если вы хотите охватить файлы во всей иерархии в /data/all, вы можете включить globstar вариант, если вы используете Bash (я считаю, что это будет "просто работать" на Zsh), а затем использовать ** сопоставить все файлы:

shopt -s globstar
for file in ./**; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done

Что я делаю неправильно?

Вы используете перенаправление > ../pos/'{}' как будто это было обработано find или же awk но перенаправления обрабатываются оболочкой. В вашем случае это означает, что вы можете перенаправить только вывод всей find (не выводится awk).

Обратите внимание, что вам обычно не нужно использовать подстановочный знак, как * для начального пути find, Это общий способ find . что вы хотели сделать или есть какая-то причина для find *?

Решения

Здесь мы будем сохранять гибкость find в отличие от решения Якобо де Вера. Бежать awk в цикле оболочки:

find . -type f -print0 |
  while read -r -d $'\0' x; do
    awk '{print $2}' "$x" > "../pos/$(basename "$x")"
  done

Оригинальный способ с -exec будет менее эффективным, потому что для каждого файла будет запущена оболочка в дополнение к awk и многоуровневое экранирование здесь довольно сложно:

find . -type f -exec sh -c 'awk "{print \$2}" "{}" > "../pos/{}"' \;

Также может быть альтернативное решение сделать перенаправление внутри awk,

find / path -exec ls -l {} \; | awk '{print $ 1}'

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