J'ai récemment téléchargé certains fichiers que je souhaite nommer. Il est possible de faire quelque chose comme:
rename 's/ /_/g' $(ls -t | head -n5)
En fait, je voudrais renommer les 5 derniers fichiers téléchargés.
Une idée?
Tout d'abord, je dois noter que l'analyse de ls
n'est généralement pas recommandée. Sa sortie est destinée à la consommation humaine et cette solution échouera pour certains noms de fichiers légitimes (comme ceux contenant des caractères de nouvelle ligne, par exemple).
Cela dit, la solution la plus simple semble utiliser ls
(car find
ne propose pas d’option de tri par date de modification). Pour cela, vous pouvez utiliser des tubes et la commande xargs
pour exécuter le changement de nom final.
En bref:
ls -1t | head -n5 | xargs -I {} rename 's/ /_/g' {}
Ceci utilise votre commande d'origine presque exactement, mais avec xargs
pour effectuer l'achèvement final. xargs
prendra un certain nombre d'arguments séparés par une nouvelle ligne et les transmettra tous à une seule commande rename
.
Cela devrait fonctionner - mais l'analyse ls
est fragile. Cela casse pour les noms de fichiers contenant le caractère de nouvelle ligne; utiliser une commande destinée à analyser comme find
serait bien mieux.
Cependant, je ne sais pas comment trier par date de dernière modification avec find
. Si quelqu'un d'autre sait comment faire cela, vous obtiendrez probablement quelque chose comme:
find . -mindepth 1 -maxdepth 1 -print0 | sort <???> -Z | head -z -n5 | xargs -0 rename 's/ /_/g'
Si <???>
était un argument valide, cette chaîne de commandes indiquerait à find
de produire les fichiers du répertoire en cours séparés par un caractère NUL, puis sort
, head
et xargs
accepterait tous cela comme un suppresseur plutôt que comme une nouvelle ligne - ce qui rend le processus beaucoup plus cohérent. N'hésitez pas à commenter ou à modifier ceci si vous savez comment faire cela et souhaitez remplacer la réponse ls
par cette partie inférieure.
Comme déjà indiqué, l'analyse ls
est fragile . Cela se brisera si vos noms de fichiers ont un type d'étrangeté quelconque (espaces, nouvelles lignes, caractères de contrôle, etc.). Puisque vous souhaitez remplacer les espaces par _
, votre approche suggérée échouera. Un moyen sûr de le faire serait:
stat --printf '%n/%Y\0' * | sort -rz -t'/' -k 2 | head -z -n 3 |
cut -d'/' -z -f 1 | xargs -0 Perl-rename 's/ /_/g'
stat --printf '%n/%Y\0' *
: ceci affichera le nom (%n
) de chaque fichier ou répertoire du répertoire actuel suivi d'une barre oblique (/
; j'utilise une barre oblique car elle n'est pas autorisée dans un nom de fichier peut donc être utilisé en toute sécurité comme séparateur) et le temps de modification du fichier en secondes depuis l’époque (%Y
) et enfin un caractère NULL (\0
).sort -rz -k 2
: ceci prend une entrée séparée par NULL (-z
) et la trie dans l'ordre inverse (-r
) en fonction de la valeur dans le second /
- séparé (-t'/'
) de chaque ligne (-k 2
).head -z -n 5
: conserve les 5 premières lignes (-n 5
) séparées par un zéro (-z
).cut -d'/' -z -f 1
: affiche le premier champ (-f 1
) /
- séparé (-d /
) de données non délimitées (-z
).Je viens d'essayer ls -q
:
IFS='
'
for file in `ls -tr1q|tail -n5`; do
rename 's/ /_/g' "$file"
done
Est-ce que le renommage souhaité, même pour les noms de fichiers avec des caractères de nouvelle ligne ou autres caractères de contrôle, bien que cela donne une erreur:
Unsuccessful stat on filename containing newline at /usr/bin/rename line 59
(avec Perl v5.20.2)