Qu'est-ce qu'une bonne commande pour supprimer des espaces, des tirets et des traits de soulignement de tous les fichiers d'un répertoire ou des fichiers sélectionnés?
J'utilise la commande suivante avec Thunar Custom Actions pour slugifier les noms de fichiers:
for file in %N; do mv "$file" "$(echo "$file" | tr -s ' ' | tr ' A-Z' '-a-z' | tr -s '-' | tr -c '[:alnum:][:cntrl:].' '-')"; done
Mais cette commande ne remplace que les espaces par des tirets / tirets et des caractères plafonnés en minuscules.
J'ai utilisé la commande suivante dans le terminal pour supprimer des espaces de milliers de noms de fichiers dans un dossier, et cela a fonctionné assez rapidement:
rename "s/ //g" *
Encore une fois, il supprime uniquement les espaces, et non les tirets / tirets et les soulignements également.
Idéalement, je ne veux pas d'espaces, de tirets / tirets et de soulignements dans mes noms de fichiers. Et ce serait formidable si la commande pouvait être utilisée avec des actions personnalisées Thunar sur les fichiers sélectionnés.
la source
rename -i "s/[-_ ]//g" *
echo $file | sed -e 's/[ _-]//g'
; faitRéponses:
La version
rename
fournie avec leperl
package prend en charge les expressions régulières:Alternativement,
L'
-i
indicateurrename
utilisera le mode interactif, invitant si la cible existe déjà, au lieu d'écraser silencieusement.Le renommage de Perl est parfois appelé
prename
.Renommer de Perl contre renommer d'Utilis-Linux
Sur les systèmes de type Debian, le changement de nom de perl semble être la valeur par défaut et les commandes ci-dessus devraient simplement fonctionner.
Sur certaines distributions, l'
rename
utilitaire d'util-linux est la valeur par défaut. Cet utilitaire est totalement incompatible avec Perlrename
.Tous: Tout d' abord, vérifiez si Perl
rename
est disponible sous le nomprename
.Debian: le renommage de Perl devrait être la valeur par défaut. Il est également disponible en
prename
. L'rename
exécutable, cependant, est sous le contrôle de/etc/alternatives
et aurait donc pu être modifié en quelque chose de différent.archlinux: Exécuter
pacman -S perl-rename
et la commande est disponible en tant queperl-rename
. Pour un nom plus pratique, créez un alias. (Pointe du chapeau: ChiseledAbs)Mac OSX Selon cette réponse ,
rename
peut être installé sur OSX en utilisant homebrew via:Téléchargement direct:
rename
est également disponible auprès de Perl Monks:la source
rename
parlez-vous. Celui de util-linux -2.24.2-1.fc20.x86_64 ne prend pas en charge les expressions régulières.rename
utilisée par l'OP ressemble à laperl
version et non à lautil-linux
version.rename
page de manuel de la version util-linux . Quoi qu'il en soit, en plus de cette note, l'important est que le PO ait obtenu sa réponse (et vous avez une note positive de ma part :-D).pacman -S perl-rename
alors je suppose que vous pouvez alias.Je remplacerais toutes ces
tr
commandes, par unesed
commande de substitution, par exemple:la source
Sans compter
mv
, vous n'avez pas vraiment besoin d'un processus extérieur pour cela - vous pouvez en quelque sorte les faire caca .Cependant, cela signifie une
mv
invocation par fichier, et c'est probablementrename
mieux. Bien que cela devrait fonctionner avec seulement un POSIXmv
dans$PATH
et un shell POSIX.Donc, j'ai trouvé une sorte de démo folle pour ça. L'ensemble de test est généré comme:
En premier lieu, je serai le premier à reconnaître que la commande ci-dessus produit des résultats qui peuvent être plus facilement obtenus par d'autres moyens. Mais d'autres moyens ne démontreraient probablement pas aussi bien ce qui pourrait être fait avec
$IFS
un peu d' imagination (malade?) .Le premier morceau est donc assez simple:
tee
transmet 5 copies de son entrée - le document hérité appeléCGEN
dd
bloque son entrée par des sauts de ligne à 90 octets par bloc et des tuyaux qui ...sed
joint 2 de ces blocs sur deux\n
caractères ewline,'
cite les résultats et ajoute la chaînetouch --
à chaque cycle de ligne avant de passer à ...sh
qui exécute ensuite toutes les entrées sous forme de commandes shellLe
#CGEN
peu que ... Eh bien, brièvement ...le fond
printf
imprime 252 0sle suivant du dernier reçoit 252
''
arguments de chaîne nulle et pour chacun imprime le contenu de$n
suivi de la chaîne" $i "
eval
interprète les arguments du suivantprintf
avant d'imprimer les résultats de cette interprétation sous forme de nombres octaux précédés de 2 contre-obliques par morceaule dernier
printf
affiche les valeurs d'octets pour ces octaux 2 à la fois, suivi de la chaîne-_ ---___
pour chaque paire$n
est initialisé en une équation qui augmentera$i
d'une unité pour chaque évaluation, sauf qu'il ignore les valeurs 10, 39 ou 47 - (qui sont respectivement\n
ewline,'
single-quote et/
slash en ASCII décimal)Le résultat final est un répertoire contenant beaucoup de noms de fichiers vraiment laids contenant tous les octets de mon jeu de caractères de 1 à 255, à l'exception du guillemet simple (ignoré uniquement pour éviter une autre
sed s///
instruction) et de la/
barre oblique. Ces noms de fichiers ressemblent à ceci:Maintenant, je vais obtenir des données sur ces fichiers:
PRODUCTION
D'accord. Maintenant enfin, à l'action:
PRODUCTION
Succès! Vous pouvez voir par vous-même:
la source
IFS
+printf
set -- 'some arbitrary' args; eval printf '"%s\n"' "$(IFS=0; printf ' "$@" %s' $(printf %025d))"
new="$(IFS=" -_"; printf %s $1)"
bifurque un sous-shell (sauf dans ksh93) et a des problèmes avec les sauts de ligne. Une autre option est d'utiliserIFS=' -_'; set -- $1; IFS=; new="$*"
(et de changer votre boucle while en boucle for)[ -e x ]
retournera false six
est un lien symbolique vers un fichier inexistant ou non accessible.si vous avez perl, vous devez généralement renommer. tu peux faire:
et montrez comment ce script est écrit:
Ce script ne prend pas en charge l'indicateur -i (c'est la version de mon système), mais peut-être que le vôtre le prend en charge. Et les arguments. Le premier est les expressions régulières au format PCRE, cela fonctionne comme un filtre, modifiez le nom d'entrée en nom de sortie. Liste des noms d'entrée que vous donnez par l'astérisque '*'. par exemple, vous faites:
en vrai '*' peut être étendu à:
Lorsque vous avez de très gros fichiers, vous êtes pris au piège. shell étendra votre ligne plus longtemps que le système n'accepte. alors vous pouvez contourner ce problème en utilisant find ou xargs. l'utilisation de 'find' est un problème, car le changement de nom sera appelé plusieurs fois égal au nombre de fichiers dans le répertoire. mieux utiliser xargs avec l'option -r. un appel de renommage modifie plusieurs fichiers. par exemple:
dernier problème, qu'est-ce que cela signifie:
il s'agit d'une expression régulière pour modifier les noms. après le premier «/» est l'espace. cela est détecté et remplacé par une chaîne après le deuxième «/». Mais il y a une chaîne vide terminée par un troisième '/', puis l'espace n'est remplacé par rien. L'option 'g' rend cette expression répétitive. expression marchera pour tous les noms du début à la fin et détectera tous les espaces.
Mais que faire si vous avez un caractère de tabulation ou un autre caractère «blanc»? il y a un remplacement pour ce '\ s'. quels autres personnages inutiles? ajoutez-le simplement à l'expression. Tous se ferment avec des crochets, par exemple:
C'est tout. voyez-vous la similitude? Je pense que vous devriez lire man perlrequick et man perlretut, cela vous explique (j'espère) comment fonctionne l'expression régulière. vous pouvez utiliser la commande rename dans votre propre script si vous en avez besoin.
la source
La
sh
boucle de shell suivante supprimera tous les espaces, les traits de soulignement et les tirets des noms de fichiers dans le répertoire actuel, en prenant soin de ne pas écraser les fichiers existants:Pour
bash
etksh
, et étant un peu plus verbeux avec la logique:Retirez-le
echo
lorsque vous êtes certain qu'il fait ce que vous voulez qu'il fasse.La
tr
commande supprimera (-d
) tout caractère de l'ensemble de caractères donné (' _-'
). Il est important d'avoir le tiret au tout début ou à la fin de l'ensemble, sinon il sera interprété comme une plage de caractères.la source