A seguir, é uma correção direta da sua abordagem:
find . -type f -name 'file*' -exec sh -c 'x="{}"; mv "$x" "${x}_renamed"' \;
No entanto, isso é muito caro se você tiver muitos arquivos correspondentes, porque você inicia um shell novo (que executa a mv
) para cada correspondência. E se você tiver caracteres engraçados em qualquer nome de arquivo, isso explodirá. Uma abordagem mais eficiente e segura é a seguinte:
find . -type f -name 'file*' -print0 | xargs --null -I{} mv {} {}_renamed
Ele também tem o benefício de trabalhar com arquivos com nomes estranhos. Se for find
compatível, isso pode ser reduzido para
find . -type f -name 'file*' -exec mv {} {}_renamed \;
A xargs
versão é útil quando não estiver sendo usada {}
, como em
find .... -print0 | xargs --null rm
Aqui rm
é chamado uma vez (ou com muitos arquivos várias vezes), mas não para todos os arquivos.
Eu removi a basename
pergunta em você, porque provavelmente está errado: você mudaria foo/bar/file8
para file8_renamed
, não foo/bar/file8_renamed
.
Edições (como sugerido nos comentários):
- Adicionado encurtado
find
semxargs
- Etiqueta de segurança adicionada
x
é inútil: afind . -type f -name 'file*' -exec mv {} "{}_renamed" \;
xargs
versão tem a mesma eficiência do primeiro exemplo / /x
que há apenas diretamente corrigir a abordagem do autor da questão.{}
diretamente em umsh -c "…"
comando shell ( ) - você deve sempre transmiti-lo como argumento. (2) Nem todas as versões defind
suporte à{}_renamed
construção. (3) Não entendo sua afirmação quexargs
é útil para remover arquivos (ao contrário de renomeá-los).xargs
não émv
vs.rm
, mas o uso de{}
vs. sem. O primeiro é semelhante amv file1 file1_renamed; mv file2 file2_renamed
enquanto o segundo érm file1 file2
.Depois de tentar a primeira resposta e brincar um pouco, descobri que isso pode ser feito um pouco mais curto e menos complexo usando
-execdir
:Parece que também deve fazer exatamente o que você precisa.
fonte
find
implementações que suportam-execdir
e{}
não como um todo, também é a mais segura. Você pode querer adicionar um-i
amv
(e-T
se o seumv
suporte) #mv
um prompt ou em adição a ele, você pode (sem dúvida, dependendo de sua implementação dofind
suporte) também usar o-okdir
que produzirá o comando a ser executado antes de executá-lo.-depth
também é uma boa idéia se você também tocar em nomes de diretório.-execdir
tem uma desvantagem muito chato,find
se recusa a fazer qualquer coisa sePATH
contém os caminhos relativos ... askubuntu.com/questions/621132/...find: The relative path XXX is included in the PATH environment
Outra abordagem é usar um
while read
loop overfind
output. Isso permite o acesso a cada nome de arquivo como uma variável que pode ser manipulada sem ter que se preocupar com problemas adicionais de custo / segurança em potencial de gerar umsh -c
processo separado usandofind
a-exec
opção de 's .E se o shell sendo usado suportar a
-d
opção de especificar umread
delimitador, você poderá suportar arquivos com nomes estranhos (por exemplo, com uma nova linha) usando o seguinte:fonte
Quero expandir a primeira resposta e observe que isso não funcionará para acrescentar ao nome do arquivo, pois o
./
prefixo do caminho está presente no argumento do nome do arquivo.Modificando a resposta de Thomas Erker, considero esta uma abordagem mais genérica
Opções do xargs:
--null
Indica que cada argumento passadostdin
termina com um caractere nulo (\0
). Dessa forma, o nome do arquivo pode conter espaços, caso contrário, cada palavra será ameaçada como um parâmetro diferente para omv
comando.-I replace-str
Cada ocorrência dereplace-str
será substituída pelo argumento lidostdin
. Portanto, você pode alterá-lo para outra string, se precisar.fonte
pringf "%f\0"
vez de aprint0
?-print0
produzirá./
prefixos sePATTERN
contiver metacaracteres de shell que atrapalham ao renomear para algo que prefixa os nomes originais. (por exemplo mudança de nome0 - foo.txt
para00 - foo.txt
,1 - bar.txt
a01 - bar.txt
, etc.)Eu era capaz de fazer algo semelhante com o
for
,find
emv
.Ele encontra todos os
config.yml
arquivos e os renomeia paraconfig.yml.bak
fonte
for
e executar uma operação em massa.