Como posso mover centenas de arquivos cujas palavras-chave (ID) de seus nomes de arquivo estão listadas em um arquivo de texto?

Como posso mover centenas de arquivos cujas palavras-chave (ID) de seus nomes de arquivo estão listadas em um arquivo de texto?

Preciso mover centenas de arquivos cujo nome inclui um número de identificação e esses números estão listados linha por linha em um arquivo de texto.

Por exemplo:

The content of `ID.txt`:

1231245
1435466
3454656
3356646

Arquivos que preciso mover:

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

Responder1

Que tal (se o seu shell fornecer "substituição de processo")

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

Remova o eco se estiver satisfeito com o resultado.

EDITAR(proposta por Stéphane Chazelas)

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

Remova o -nse estiver satisfeito com o resultado.

Responder2

Supondo que os nomes dos arquivos não contenham espaços em branco, novas linhas, barras invertidas ou aspas e um shell como ksh, zsh ou bash com suporte para substituição de processos, você poderia fazer:

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

Responder3

  • Você pode fornecer grepo argumento -f FILEpara corresponder às expressões em FILE, um por linha.
  • ID.txtprecisa ser ligeiramente modificado por sedpara que corresponda exatamente ao que você deseja: a ^no início de cada linha para fazer com que o número corresponda ao início de uma linha e _no final para que a 123não corresponda 123123_.
  • ls -1listará um arquivo por linha.
  • xargs -I FOOBARsubstitui ocorrências de FOOBAR pela linha de entrada em vez de anexar a linha de entrada.

Então:

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

Responder4

Uma solução pura bash:

while IFS= read -r p; do mv ${p}* /target; done < ID.txt
  • < ID.txtdá o arquivo como entrada
  • while IFS= read -r ppula pelas linhas
    • mv ${p}* /targetmova todos os arquivos começando com o número do arquivo para o /targetdiretório.

Você pode escrever echona frente do mvcomando para controlar quais comandos serão executados:

$ 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

informação relacionada