Como mover arquivos especificados em um arquivo de texto para outro diretório no BASH? [duplicado]

2

Eu tenho um diretório com mais de 400 imagens. A maioria deles é corrupta. Eu identifiquei os bons. Eles estão listados em um arquivo de texto (há mais de 100 deles). Como posso movê-los todos de uma vez para outro diretório no BASH?

    
por Weylyn Savan 05.11.2017 / 23:32

4 respostas

1

Existem várias maneiras de fazer isso que vêm imediatamente à mente:

  1. Usando um loop while
  2. Usando xargs
  3. Usando o rsync

Suponha que os nomes dos arquivos estejam listados (um por linha) em files.txt e queremos movê-los do subdiretório source/ para o subdiretório target .

O loop while pode ser algo assim:

while read filename; do mv source/${filename} target/; done < files.txt

O comando xargs pode ser parecido com isto:

cat files.txt | xargs -n 1 -d'\n' -I {} mv source/{} target/

E o comando rsync pode ser algo assim:

rsync -av --remove-source-files --files-from=files.txt source/ target/

Pode valer a pena criar um sandbox para experimentar e testar cada abordagem, por exemplo:

# Create a sandbox directory
mkdir -p /tmp/sandbox

# Create file containing the list of filenames to be moved
for filename in file{001..100}.dat; do basename ${filename}; done >> /tmp/sandbox/files.txt

# Create a source directory (to move files from)
mkdir -p /tmp/sandbox/source

# Populate the source directory (with 100 empty files)
touch /tmp/sandbox/source/file{001..100}.dat

# Create a target directory (to move files to)
mkdir -p /tmp/sandbox/target

# Move the files from the source directory to the target directory
rsync -av --remove-source-files --files-from=/tmp/sandbox/files.txt /tmp/sandbox/source/ /tmp/sandbox/target/
    
por 06.11.2017 / 00:02
3
Solução

Rápida com o GNU parallel :

Digamos que os nomes dos arquivos de imagem "good" estejam listados no arquivo good_img.txt e a pasta de destino seja denominada good_images .

cat good_img.txt | parallel -m -j0 --no-notice mv {} good_images 
  • -m - insira tantos argumentos quanto o comprimento da linha de comando permitir. Se vários trabalhos estiverem sendo executados em paralelo: distribua os argumentos uniformemente entre os trabalhos

  • -j N - número de jobslots. Execute até N jobs em paralelo. 0 significa o maior número possível. O padrão é 100%, que executará um trabalho por núcleo da CPU.

por 05.11.2017 / 23:49
1

Se houver um nome de arquivo por linha:

xargs -d \n echo mv -t /target/directory
    
por 05.11.2017 / 23:37
1

Enquanto você solicitou uma solução bash, você pode realmente ter pensado em uma solução baseada em linha de comando. Outros têm fornecido usando uma variedade de ferramentas de linha de comando. Aqui está uma solução que usa um bash builtin ( readarray / mapfile ) para ler o conteúdo do arquivo de texto para passar esses nomes de arquivos para o comando mv :

Configuração

$ touch {a..z}.jpg "bad one.jpg" "good one.jpg"
$ mkdir good
$ cat saveus
j.jpg
good one.jpg
z.jpg

Preparação

$ readarray -t < saveus.txt
$ declare -p MAPFILE
declare -a MAPFILE='([0]="j.jpg" [1]="good one.jpg" [2]="z.jpg")'

Faça isso

$ mv -- "${MAPFILE[@]}" good/

Confirmação

$ ls -1 good/
good one.jpg
j.jpg
z.jpg
$ ls "good one.jpg" j.jpg z.jpg
ls: cannot access good one.jpg: No such file or directory
ls: cannot access j.jpg: No such file or directory
ls: cannot access z.jpg: No such file or directory
    
por 06.11.2017 / 01:22