É possível renomear arquivos selecionados por ls?

3

Eu tenho alguns arquivos que baixei recentemente e quero nomear. É possível fazer algo como:

rename 's/ /_/g' $(ls -t | head -n5) 

Na verdade, gostaria de renomear os últimos 5 arquivos baixados.

Alguma ideia?

    
por dmx 28.04.2017 / 08:08

3 respostas

2

Primeiro, preciso observar que a análise de ls geralmente não é recomendada. Sua saída é destinada ao consumo humano, e esta solução falhará em alguns nomes de arquivos legítimos (como aqueles que contêm caracteres de nova linha, por exemplo)

Com isso dito, a solução mais simples parece estar usando ls (pois find não oferece uma opção de classificação por data de modificação). Para isso, você pode usar pipes e o comando xargs para executar a renomeação final.

Resumindo:

ls -1t | head -n5 | xargs -I {} rename 's/ /_/g' {}

Isso usa quase exatamente o comando original, mas com xargs para a conclusão final. xargs aceitará vários argumentos separados por nova linha e passará todos eles para um único comando rename .

Advertências

Isso deve funcionar, mas analisar ls é frágil. Isso é interrompido para nomes de arquivos que contêm o caractere de nova linha; usar um comando que serve para analisar como find seria muito melhor.

No entanto, não sei como classificar pela data da última modificação com find . Se alguém souber como fazer isso, você provavelmente terminará com algo como:

find . -mindepth 1 -maxdepth 1 -print0 | sort <???> -Z | head -z -n5 | xargs -0 rename 's/ /_/g'

Se <???> fosse um argumento válido, essa cadeia de comando informaria find aos arquivos de saída no diretório atual separados por um caractere NUL e, em seguida, sort , head e xargs aceitariam isso como o deliminador em vez de uma nova linha - tornando todo o processo muito mais consistente. Sinta-se à vontade para comentar ou editar isso se você souber como fazer isso e quiser substituir a ls answer por essa parte inferior.

    
por daboross 28.04.2017 / 09:38
1

Como já foi mencionado, parsing ls é frágil . Ele irá quebrar se seus nomes de arquivos tiverem qualquer tipo de estranheza (espaços, novas linhas, caracteres de controle, etc.). Como você deseja substituir espaços com _ , sua abordagem sugerida falhará. Uma maneira segura de fazer isso seria:

stat --printf '%n/%Y
stat --printf '%n/%Y%pre%' * | sort -rz -t'/' -k 2 | head -z -n 3 | 
    cut -d'/' -z -f 1 | xargs -0 perl-rename 's/ /_/g'
' * | sort -rz -t'/' -k 2 | head -z -n 3 | cut -d'/' -z -f 1 | xargs -0 perl-rename 's/ /_/g'
  • stat --printf '%n/%Y%n' * : isso imprimirá o nome ( / ) de todos os arquivos ou diretórios no diretório atual seguido por uma barra ( %Y ; estou usando uma barra, pois isso não é permitido em um nome de arquivo, portanto, pode ser usado como separador) e o tempo de modificação do arquivo em segundos desde a época ( sort -rz -k 2 ) e finalmente um caractere NULL ( -z ).
  • -r : isso utilizará entrada separada em NULL ( / ) e ordenará em ordem reversa ( -t'/' ) com base no valor do segundo campo -k 2 -separated ( head -z -n 5 ) de cada linha (% código%).
  • -n 5 : mantenha as primeiras 5 linhas ( -z ) separadas por nulo ( cut -d'/' -z -f 1 ).
  • -f 1 : imprime o primeiro campo ( / ) -d / -separated ( -z ) de dados delimitados por nulo ( %code% ).
por terdon 28.04.2017 / 11:25
0

Eu acabei de testar o ls -q :

IFS='
'
for file in 'ls -tr1q|tail -n5'; do
  rename 's/ /_/g' "$file"
done

Faz a renomeação desejada, mesmo para nomes de arquivos com nova linha ou outros caracteres de controle, apesar de dar um erro:

Unsuccessful stat on filename containing newline at /usr/bin/rename line 59

(com perl v5.20.2)

    
por Philippos 28.04.2017 / 12:33