Мне удалось добиться этого с помощью следующего скрипта bash:
#!/bin/bash
files='/path/to/files'
for file in "$files/"*.jpg; do
tag=$(grep '_tags_' "${file/.jpg/.txt}")
bname=${file%.jpg}
mv "$file" "${bname}${tag}.jpg"
done
Это будет перебирать все .jpg
файлы по указанному вами пути.
tag
выполнит поиск строки _tags_
в файле .txt
с тем же именем, что и текущий файл .jpg
, над которым он работает, и будет установлен на всю эту строку.
bname
будет установлено базовое имя текущего файла, над которым он работает (без расширения)
Затем он переименует файл в name/tag.jpg (Таким образом, в случае с примером2675_tags_mountains_daylight_oregon.jpg
)
Не нужно xargs
или что-то сложное. Если все файлы находятся в одном каталоге, достаточно сделать:
$ while read string; do
mv "$string"_*./Data;
done < strings.txt
Или, если ваши имена могут начинаться с -
или в них могут быть другие странные символы, используйте:
$ while read -r string; do
mv -- "$string"_*./Data;
done < strings.txt
xargs bash -O nullglob -c '
for prefix do
set -- "$prefix"*.faa
[ "$#" -gt 0 ] && mv -- "$@"./Data
done' sh <strings.txt
При этом используется xargs
для передачи строк в strings.txt
сценарию в -строке bash
пакетами.
Для каждой строки скрипт в строке -bash
проверяет, есть ли какие-либо имена файлов, соответствующие строке в текущем каталоге, (добавляя *.faa
в конец для создания шаблона ), и если поэтому они перемещаются в каталог Data
, который, как предполагается, уже существует.
Параметр оболочки nullglob
установлен для скрипта в строке -, чтобы гарантировать, что, если созданный шаблон не не совпадает ни с чем, шаблон удаляется (, а не сохраняется нераскрытым ).
Я явно проверяю соответствие шаблона, потому что в вашем примере есть строки, которые не соответствуют ни одному из показанных вами имен файлов. Это делается путем присвоения списку позиционных параметров результата расширения глобуса и последующей проверки того, превышает ли длина списка($#
)ноль.
Очевидно, вы могли бы сделать это и без xargs
вот так:
shopt -s nullglob
while IFS= read -r prefix; do
set -- "$prefix"*.faa
[ "$#" -gt 0 ] && mv -- "$@"./Data
done <strings.txt
Это все равно завершится ошибкой, если одна из ваших строк префикса совпадет с многими тысячами имен файлов, (mv
командная строка станет слишком длинной ). Если это так, вы, возможно, использовали бы
shopt -s nullglob
while IFS= read -r prefix; do
set -- "$prefix"*.faa
if [ "$#" -gt 0 ]; then
printf '%s\n' "$@" | xargs sh -c 'mv -- "$@"./Data' sh
fi
done <strings.txt
Предполагается, что ни строки префиксов, ни имена файлов не содержат встроенных символов новой строки.
Быстрый и грязный взлом:cat strings.txt| xargs -i sh -c 'mv {}* your/path/'>&/dev/null
Менее правильный хак:export dir=$(ls -1); cat strings.txt| xargs -i sh -c 'grep "^{}" <<<$dir && mv {}* your/path'; dir=""