Como você move arquivos em massa para um diretório com segurança?

10

Como posso mover arquivos para um diretório em que possa haver centenas ou milhares de arquivos no diretório, e você pode não ter certeza sobre a existência de dupes ... Qual método você usaria?

Como lidar com os enganadores varia, às vezes sobrescrevemos, às vezes precisamos ser mais seguros. E / S pode ser importante porque esses são servidores de produção. Mas, dada a quantidade, um prompt para arquivos não duplicados não é uma opção. Preservação de permissões, registros de data e hora, etc., é importante. Normalmente, não sabemos quais são os dados.

Oh e usando mvnão é necessária, rsync, cpsoluções de boas-vindas.

note: estamos executando o CentOS 5.5, por isso, deixe-me saber se ele não funcionará lá por ser um recurso mais recente ...

xenoterracida
fonte
O que você gostaria de fazer com os tolos?
@Iain depende da situação? Eu trabalho em um host da Web ... realmente depende mve se nos preocupamos com a preservação no caso de ... e se já fizemos um backup. Esta questão é bastante aberta. Estou apenas procurando boas opções, e talvez um comentário sobre se pode ou não morder você e como.
Xenoterracide
Presumo que haja muitos arquivos para o shell manipular mv * ../ou mv -i * ../?
Michael Mrozek
@ Michael, tenho certeza que varia ... em alguns casos provavelmente não. Em alguns casos, talvez. Estou tentando pegar o maior número possível de opções para o meu trabalho.
Xenoterracide

Respostas:

6

Eu recomendaria usar o rsync do pai:

rsync -avPr -b --suffix='-original' child/* .

que fará o backup de todos os arquivos duplicados existentes no pai para o arquivo - original .

Tok
fonte
Acho que -aimplica-r
xenoterracide
@xenoterracide - Direito você 'r'
Tok
@Tok é possível fazer a cópia como hardlinks? para não desperdiçar IO. (like -lfor cp)
xenoterracide
@xenoterracide - Você pode usar os sinalizadores -Hou --hard-linksdo rsync para preservar os links físicos .
Tok
1
@xenoterracide - Você pode usar o --link-dest=DIRsinalizador para obter esse comportamento como: o rsync -avP --link-dest=/path/to/src /path/to/src/* /path/to/dest/qual vinculará dst / quaisquer arquivos inalterados entre src e src, neste caso todos os arquivos. Normalmente, você vê esse sinalizador usado quando deseja vincular novamente os arquivos de backup sem copiar seus dados, como --link-dest=/most/recent/backup.
Tok
4
cp -bal . ..

Isso copiará tudo do diretório atual para o diretório acima, mantendo todas as permissões, usando hardlinks para minimizar o IO, se possível, e em duplicatas ele cria o nome do arquivo ~

depois disso

rm -rf . ; cd .. ; rmdir <originaldir>;
xenoterracida
fonte
provavelmente corre para o grande número de problemas de arquivos ... mas não é intensivo em IO como o rsync.
Xenoterracide
2

Neste exemplo, os arquivos serão movidos de '/ parent / old-dir' para '/ parent':

cd /parent

rsync -av --progress old-dir/ .

rm -rf old-dir

Pelas regras do rsync, ele substituirá os dups por arquivos mais recentes do old-dir.

Alexander Pogrebnyak
fonte
1

Podes tentar

find . -maxdepth 1 -print0 | xargs -I '{}' -r0 mv '{}' ..

que sobrescreverá arquivos duplicados em ..

Você pode usar mv -u '{}' para não sobrescrever se o dupe in .. for o mesmo ou mais recente


fonte
por que encontrar pipe para xargs? por que não usar +
xenoterracide
1
@xenoterracide - Hábito e portabilidade (é uma extensão GNU). Além disso, eu apenas tentei e não consigo descobrir como passar o segundo parâmetro ..para o mv '{}' +comando, pois o + apenas adiciona ao final.
@Iain the + está no POSIX, na verdade me disseram anteriormente que a descoberta do GNU estava atrasada para obtê-lo.
Xenoterracide
Você está certo, mas eu ainda não consigo descobrir uma maneira de usar .. #
2
@xenoterracide: Com coreutils GNU: -exec mv -t .. -- {} +. Portably: -exec sh -c 'mv -- "$@"' _ {} +.
Gilles 'SO- stop be evil'
1

mv -i somente solicita se o destino existir.

yes n | mv -i …move todos os arquivos que não existem no diretório de destino. No FreeBSD e OSX, você pode reduzi-lo para mv -n ….

Observe que nenhum deles mesclará um argumento de diretório com um diretório existente com o mesmo nome no diretório de destino.


Uma questão separada é como agir em todos os arquivos no diretório atual. Há dois problemas: pegar todos os arquivos ( *omite arquivos de ponto) e não executar em uma linha de comando. No Linux (ou mais geralmente com o GNU find e o GNU coreutils):

find . -mindepth 1 -maxdepth 1 -exec mv -i -t .. -- {} +

Com o GNU find mas não o GNU coreutils (ou o GNU coreutils mais antigo):

find . -mindepth 1 -maxdepth 1 -exec sh -c 'mv -i -- "$@" "$0"' .. {} +

Portably:

find . -name . -o -exec sh -c 'mv -i -- "$@" "$0"' .. {} -type d -prune

Como de costume, o zsh facilita as coisas. Ele não possui uma limitação de comprimento de linha de comando internamente; portanto, se você o usa interno, mvnão precisa se preocupar com isso. E você pode dizer para não ignorar arquivos de ponto com o Dqualificador glob. Limitação: isso não funciona em sistemas de arquivos (a partir do zsh 4.3.10).

zmodload zsh/files
mv -i -- *(D) ..
Gilles 'SO- parar de ser mau'
fonte
para muitos argumentos?
Xenoterracide
0

Eu disse no nosso ML

mv * ..

obviamente isso não é muito seguro ... ele substituirá as coisas. Pode ter limites que eu nunca encontrei.

xenoterracida
fonte
2
Se você tiver um grande número de arquivos, provavelmente receberá um "erro de lista muito longo".
2
Pode fazer coisas ruins se você tiver um nome de arquivo que comece com -. Ele não captura arquivos cujo nome começa com ..
Gilles 'SO- stop be evil'
0

A seguir, um modelo python que eu usei com bons efeitos no passado.

#!/usr/bin/env python
#
# Bart Kastermans, www.bartk.nl
#
# rename of collection of files in a directory
import os
import shutil

# only work on files whose name starts with a D
files = [filename for filename in os.listdir ("/Users/kasterma/Music/Audio Hijack/") if filename[0] =="D"]

for filename in files:
    shutil.move (filename, filename [:23] + ".mp3")
kasterma
fonte