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

11

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

Como lidar com dupes pode variar, às vezes sobrescrevemos, às vezes precisamos estar mais seguros. O IO pode ser importante porque 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 e timestamps, etc, é importante. Geralmente não sabemos quais são os dados.

Ah, e usar mv não é necessário, rsync , cp soluções são bem-vindas.

nota: estamos rodando o CentOS 5.5, então me avise se ele não funcionará lá devido a ser um recurso mais recente ...

    
por xenoterracide 17.12.2010 / 16:48

7 respostas

6

Eu recomendaria usar o rsync do pai:

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

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

    
por 17.12.2010 / 17:32
3
cp -bal . ..

Isto irá copiar tudo no diretório atual para o diretório acima dele, retendo todas as permissões, usando hardlinks para minimizar o IO, se possível, e em duplicatas que ele cria filename ~

depois disso

rm -rf . ; cd .. ; rmdir <originaldir>;
    
por 18.12.2010 / 12:58
1

Você pode tentar

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

que sobrescreverá arquivos dupe em ...

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

    
por 17.12.2010 / 17:00
1

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

cd /parent

rsync -av --progress old-dir/ .

rm -rf old-dir

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

    
por 17.12.2010 / 17:24
1

mv -i apenas pergunta se o destino existe.

yes n | mv -i … move todos os arquivos que não existem no diretório de destino. No FreeBSD e no OSX, você pode encurtar isso 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 os arquivos de ponto) e não executar em uma linha de comando. No Linux (ou mais geralmente com GNU find e GNU coreutils):

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

Com GNU, mas não GNU coreutils (ou GNU coreutils mais antigos):

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

Portável:

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

Como de costume, o zsh facilita as coisas. Ele não tem uma limitação de comprimento de linha de comando internamente, portanto, se você usa o mv builtin, não precisa se preocupar com isso. E você pode dizer para não ignorar os arquivos de ponto com o qualificador D glob. Limitação: isso não funciona nos sistemas de arquivos (a partir do zsh 4.3.10).

zmodload zsh/files
mv -i -- *(D) ..
    
por 17.12.2010 / 21:02
0

Eu disse no nosso ML

mv * ..

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

    
por 17.12.2010 / 17:05
0

O seguinte é um modelo python que eu usei com bom efeito 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")
    
por 17.12.2010 / 17:27