Используя 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
,