Как переместить из списка все файлы, имена которых начинаются со строки?

Мне удалось добиться этого с помощью следующего скрипта 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)

2
12.03.2020, 17:52
3 ответа

Не нужно xargsили что-то сложное. Если все файлы находятся в одном каталоге, достаточно сделать:

$ while read string; do 
    mv "$string"_*./Data; 
  done < strings.txt 

Или, если ваши имена могут начинаться с -или в них могут быть другие странные символы, используйте:

$ while read -r string; do 
    mv -- "$string"_*./Data; 
  done < strings.txt 
0
28.04.2021, 23:20
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

Предполагается, что ни строки префиксов, ни имена файлов не содержат встроенных символов новой строки.

1
28.04.2021, 23:20

Быстрый и грязный взлом: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=""

0
28.04.2021, 23:20

Теги

Похожие вопросы