Магия Bash Shell awk/xargs

Я пытаюсь немного научиться awk foo. У меня есть CSV, где каждая строка имеет формат частичное_имя_файла, путь_к_файлу. Моя цель - найти файлы (на основе частичного имени) и переместить их по соответствующим новым путям. Я хотел объединить силы find, awk и mv, чтобы добиться этого, но я застрял в реализации. Я хотел использовать awk для отделения терминов из CSV-файла, чтобы я мог сделать что-то вроде
find . -name '*$1*' -print | xargs mv {} $2{}
, где $1 и $2 — это разделенные термины из CSV-файла. У кого какие идеи?
-peace


person adbo    schedule 11.11.2011    source источник


Ответы (3)


Мне кажется, вы тут что-то перепутали. {} можно использовать только в поиске и только один раз. То есть вы не можете сделать что-то вроде find -name '*.jpg' -exec mv {} {}.png.

Сделай это:

$ cat korv
foo.txt,/hello/
bar.jpg,/mullo/
$ awk -F, '{print $1 " " $2}' korv
foo.txt /hello/
bar.jpg /mullo/

-F устанавливает разделитель, поэтому приведенное выше будет разделено с помощью «,». Затем добавьте * к именам файлов:

$ awk -F, '{print "*"$1"*" " " $2}' korv
*foo.txt* /hello/
*bar.jpg* /mullo/
**

Это показывает, что у меня есть пустая строка. Нам не нужно это совпадение, поэтому мы добавляем правило:

$ awk -F, '/[a-z]/{print "*"$1"*" " " $2}' korv
*foo.txt* /hello/
*bar.jpg* /mullo/

Выглядит хорошо, поэтому инкапсулируйте все это в mv с помощью подоболочки:

$ mv $(awk -F, '/[a-z]/{print "*"$1"*" " " $2}' korv)
$

Сделанный.

person bos    schedule 11.11.2011
comment
да я немного перепутал там. Классный раствор и хорошее объяснение. Большое спасибо - person adbo; 11.11.2011
comment
Нет, xargs -i, конечно же, также поддерживает {}, но принимает только один аргумент за раз. - person tripleee; 11.11.2011
comment
echo foo | xargs -n 1 echo mv {} {}.txt =› mv {} {}.txt foo для меня. - person bos; 11.11.2011
comment
Вы забыли -i от xargs -i. - person tripleee; 11.11.2011
comment
Кроме того, запуск его в обратных кавычках скопирует все файлы в конечный каталог назначения. - person tripleee; 11.11.2011
comment
Просто чтобы объяснить предложение Tripleee (я полагаю, вы имели в виду заглавную -I): echo foo | xargs -n 1 -I {} echo mv {} {}.txt => mv foo foo.txt - person Joshua Goldberg; 19.12.2012
comment
вы можете использовать {} более одного раза, например. find . -name file -exec mv {} {}.txt \; действителен. - person Milo Wielondek; 11.04.2013

Вам действительно не нужен awk для этого. На самом деле здесь нет ничего, что awk делал бы лучше, чем оболочка.

#!/bin/sh
IFS=,
while read file target; do
  find . -name "$file" -print0 | xargs -ir0 mv {} "$target"
done <path_to_csv_file

Если у вас есть специальные символы в именах файлов, вам может потребоваться настроить read.

person tripleee    schedule 11.11.2011

как насчет использования системной команды awk:

awk '{ system("find . -name " $1 " -print | xargs -I {} mv {} " $2 "{}"); }'

пример аргументов в CSV-файле: test.txt ./subdirectory/

person aleph_null    schedule 11.11.2011
comment
Спасибо за помощь. Не знал об этой команде. Таким образом, полный вызов будет выглядеть так: awk '{ system("find . -name " $1 " -print | xargs -I {} mv {} " $2 "{}"); }' path_to_csv_file? - person adbo; 11.11.2011
comment
Для чего последний '{}'? По крайней мере, для меня это работает лучше, если вы уберете это. - person tripleee; 11.11.2011
comment
@adbo: запустите его с -F для CSV-файла. Решение Bos намного лучше, если предположить, что вы хотите копировать файлы только в текущий каталог (в этом случае find становится совершенно ненужным). - person aleph_null; 11.11.2011
comment
@tripleee: Хотя это все еще работает с последним {}, вы правы в том, что в этом нет необходимости. mv file.txt ./subdir/file.txt работает так же, как mv file.txt ./subdir/. Оглядываясь назад, я бы убрал его. - person aleph_null; 11.11.2011