Eu suponho que você tenha apenas nomes de arquivos. Essa é a maneira mais simples de fazer isso:
while IFS= read -r file; do mv -v "dirA/$file" "dirB/$file"; done < listfile.txt
Eu tenho uma lista de arquivos, que eu gostaria de mover da pasta A
para a pasta B
, mas eu não quero fazer isso manualmente. Existe uma maneira mais fácil de percorrer a lista e mover todos os arquivos que estão nessa lista?
Você pode usar rsync
para movê-los, supondo que sua lista de arquivos seja um nome de arquivo por linha.
rsync -av --remove-source-files --files-from filelist.txt sourceDir/ targetDir/
Se os seus arquivos forem nomes absolutos (ou seja, os nomes começam com /
), o sourceDir
deve ser /
. Caso contrário, deve ser a raiz dos nomes relativos.
Exemplo
$ mkdir src dst
touch src/{one,two,three}
$ cat >filelist.txt <<EOF
one
two
EOF
$ ls src
one three two
$ ls dst
$ rsync -av --files-from filelist.txt --remove-source-files src/ dst/
building file list ... done
one
two
sent 165 bytes received 70 bytes 470.00 bytes/sec
total size is 0 speedup is 0.00
$ ls src
three
$ ls dst
one two
Se você deu utilitários GNU principais (ou outras implementações com esses recursos específicos), você pode usar xargs
para construir uma lista de argumentos para mv
com base na lista de arquivos:
cd A
xargs -rd '\n' -- mv -t B -- < file-list.txt
Sem os utilitários GNU, você ainda pode usar um loop de leitura lenta. No Bash isso poderia ser:
while IFS= read -r file; do
mv "A/$file" "B/$file"
done < file-list.txt
Você pode resolver isso facilmente em ViM com estas 10 etapas simples:
qa
para começar a gravar uma macro chamada "a". y$
para extrair (copiar) o nome do arquivo. imv A/
para escrever "mv A /" na frente do nome do arquivo e pressione Escape
. A B/
para escrever "B /" no final da linha e, em seguida, pressione Escape
. pj^
para colar o nome do arquivo e passar para o início da próxima linha. q
para parar de gravar a macro. VG:normal @a
para reproduzir a macro "a" até o final do arquivo. :wq rename.sh
para salvar como um script bash chamado "rename.sh" e saia. chmod +x rename.sh; ./rename.sh
para marcar o script como executável e executá-lo. Aqui está uma variante compatível com POSIX sem usar loops. Itens em file-list.txt
são separados por novas linhas.
cd A ; xargs -I{} -- mv -- {} B < file-list.txt
Obviamente, esta variante não permite nomes de arquivos contendo novas linhas. Além disso, invoca o comando mv
para cada arquivo individualmente.
A variante de David Foerster usa as extensões GNU de xargs
e mv
. Ele chamará a instância única de mv
para vários argumentos e será mais eficiente para longas listas de arquivos. Ainda não permite nomes de arquivos contendo novas linhas. Para superar essa limitação, você pode usar a opção -0
e separar os nomes dos arquivos por caracteres %code%
(NULL).
cd A ; xargs -r0 -- mv -t B -- < file-list.txt
cpio
é um arquivador padrão do Linux que também inclui um modo de passagem que torna uma maneira conveniente de copiar coisas.
É necessária uma lista de arquivos na entrada padrão, geralmente isso é geralmente roteirizado como a saída do comando find
, mas como você já tem uma lista de arquivos, vamos usar isso.
assumindo que os nomes de arquivos na lista são relativos
cd A; cpio --format=newc -pduv B < filelist.txt
instruindo cpio
, fornecendo uma lista de nomes de arquivos em stdin, para passar, criar diretórios, gravar incondicionalmente qualquer coisa já existente e imprimir uma linha de verificação, direcionando o diretório B. Usar o formato newc
permite mais que 65536 inodes, apenas no caso de você estar lidando com isso muitos