Tenho esta situação em que há muitos arquivos com nomes semelhantes (mas todos seguem um padrão) em subpastas diferentes
file1
file1 (Copy)
/folder1/file2.txt
/folder1/file2 (Copy).txt
/folder1/file3.png
/folder1/file3 (Copy).png
Cada arquivo está na mesma pasta de sua cópia e possui a mesma extensão, a diferença é que possui (Copy)
no final do nome
Quero obter todos esses arquivos e excluir o mais antigo e, eventualmente, renomear o arquivo de, por exemplo, file1 (Copy)
para file1
(ou seja, remover o (Copy)
sufixo) se precisar ser renomeado.
Eu estava pensando em usar find
e mv
, mas não sei como dizer para mover o mais recente.
Responder1
Estendidofind
+bash
solução (também precisa da implementação GNU de stat
):
find . -type f -name "* (Copy).*" -exec bash -c 'p="${0%/*}"; bn="${0##*/}";
main_bn="${bn/ (Copy)/}";
if [ -f "$p/$main_bn" ]; then
t_copy_file=$(stat -c %Y "$0"); t_main_file=$(stat -c %Y "$p/$main_bn");
if [[ $t_copy_file -gt $t_main_file ]]; then
mv "$0" "$p/$main_bn";
else
rm "$0";
fi;
fi' {} \;
p="${0%/*}"
- caminho do arquivo/caminho com nome de base cortadobn="${0##*/}"
- nome base do arquivomain_bn="${bn/ (Copy)/}"
- remova(Copy)
a substring do nome base para obter oprincipal/comumnome baseif [ -f "$p/$main_bn" ]
- se oprincipal/originalo arquivo existe (e é considerado um arquivo normal após a resolução do link simbólico)t_copy_file=$(stat -c %Y "$0")
- obter a hora da última modificação encontrada"cópia de"arquivot_main_file=$(stat -c %Y "$p/$main_bn")
- obter a hora da última modificação deoriginalarquivoif [[ $t_copy_file -gt $t_main_file ]]
- se o"cópia de"arquivo é o recente - mova-o para ooriginalum (façaoriginal) commv "$0" "$p/$main_bn"
- caso contrário - ooriginalarquivo é o recente, removendo "cópia de"arquivo com
rm "$0"
Ou um pouco mais curto com -nt
o operador de teste de arquivo ( [ newerfile –nt olderfile ]
- verifique se newerfile
foi alterado mais recentemente que olderfile
ou se newerfile
existe e olderfile
não existe):
find . -type f -name "* (Copy).*" -exec bash -c 'p="${0%/*}"; bn="${0##*/}";
main_bn="${bn/ (Copy)/}";
if [ -f "$p/$main_bn" ]; then
if [ "$0" -nt "$p/$main_bn" ]; then
mv "$0" "$p/$main_bn";
else
rm "$0";
fi;
fi' {} \;
Responder2
Pode ser mais fácil com zsh
:
setopt extendedglob # best in ~/.zshrc
for file (./**/?*" (Copy)"*(ND.)) {
base=$file:h/${${file:t}/" (Copy)"}}
[[ ! -f $base || -L $base ]] ||
if [ $file -nt $base ]; then
mv $file $base
else
rm -f $file
fi
}
Você pode querer verificar se não há file (Copy) (Copy).txt
arquivos primeiro.
**/
: qualquer nível de subdiretórioN
:nullglobexpandir para nada se não houver correspondência em vez de errarD
: inclui arquivos ocultos (D
arquivos ot) e desce para diretórios ocultos..
: incluir apenasregulararquivos (sem diretório, fifo, dispositivo, link simbólico...)$file:h
:cabeçado arquivo (parte do diretório), como emcsh
$file:t
:cauda(parte do nome do arquivo)${var/pattern/replacement}
, aqui sem substituição[[ ! -f $base || -L $base ]] ||...
pule arquivos não regulares ou links simbólicos (mesmo que apontem para arquivos regulares) como proteção.[ $file -nt $base ]
: retorna verdadeiro se$file
foi modificado pela última vezdepois$base
(ou$base
não está acessível, não devemos acontecer seguindo a verificação acima).