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

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

Мне нужно переместить сотни файлов, имена которых включают идентификационный номер, и эти номера перечислены построчно в текстовом файле.

Например:

The content of `ID.txt`:

1231245
1435466
3454656
3356646

Файлы, которые мне нужно переместить:

1231245_134.fasta
1231245_134.dna
1435466_345.fasta
1435466_345.dna
3454656_789.fasta
3454656_789.dna
3356646_104.fasta
3356646_104.dna

решение1

А как насчет (если ваша оболочка обеспечивает «подстановку процесса»)

. <(sed 's/^/echo mv /; s/$/* \/target/' ID.txt)

Если результат вас устраивает, удалите эхо.

РЕДАКТИРОВАТЬ(предложено Стефаном Шазеласом)

sed 's|.*|mv -- &_* /target/|' ID.txt | sh -v -n

Удалите, -nесли результат вас устраивает.

решение2

Предполагая, что имена файлов не содержат пробелов, символов новой строки, обратных косых черт или кавычек, а также имея оболочку вроде ksh, zsh или bash с поддержкой подстановки процессов, вы можете сделать следующее:

join -t_ <(printf '%s\n' *_* | sort -t_ -k1,1) <(sort ID.txt) |
  xargs sh -c 'exec mv -- "$@" /target' sh

решение3

  • Вы можете указать grepаргумент -f FILEдля сопоставления с выражениями в FILE, по одному на строку.
  • ID.txtнеобходимо немного изменить, sedчтобы он соответствовал только тому, что вам нужно: a ^в начале каждой строки, чтобы число совпадало в начале строки, и _в конце, чтобы a 123не соответствовало 123123_.
  • ls -1будет выведен список из одного файла в каждой строке.
  • xargs -I FOOBARзаменяет вхождения FOOBAR на входную строку, а не добавляет входную строку.

Так:

sed -e 's/^/^/' -e 's/$/_/' /path/to/ID.txt > /tmp/ID_regexp.txt
cd /old/dir
ls -1 | grep -f /tmp/ID_regexp.txt | xargs -I FILE mv FILE /new/dir

решение4

Чистое bashрешение:

while IFS= read -r p; do mv ${p}* /target; done < ID.txt
  • < ID.txtдает файл в качестве входных данных
  • while IFS= read -r pпролетает через линии
    • mv ${p}* /targetпереместить все файлы, начинающиеся с указанного номера, в указанный каталог /target.

Вы можете написать echoперед mvкомандой, чтобы контролировать, какие команды будут выполняться:

$ while IFS= read -r p; do echo mv ${p}* /target; done < ID.txt
mv 1231245_134.dna 1231245_134.fasta /target
mv 1435466_345.dna 1435466_345.fasta /target
mv 3454656_789.dna 3454656_789.fasta /target
mv 3356646_104.dna 3356646_104.fasta /target

Связанный контент