Comment Bash peut-il renommer une série de packages pour supprimer leurs numéros de version? J'ai joué avec les deux expr
et %%
, en vain.
Exemples:
Xft2-2.1.13.pkg
devient Xft2.pkg
jasper-1.900.1.pkg
devient jasper.pkg
xorg-libXrandr-1.2.3.pkg
devient xorg-libXrandr.pkg
bash
shell
file-rename
Jeremy L
la source
la source
Réponses:
Vous pouvez utiliser la fonction d'expansion des paramètres de bash
Les guillemets sont nécessaires pour les noms de fichiers avec des espaces.
la source
rename "s/-[0-9.]*//" *.pkg
Si tous les fichiers sont dans le même répertoire, la séquence
fera votre travail. La commande sed créera une séquence de commandes mv , que vous pourrez ensuite diriger vers le shell. Il est préférable d'exécuter d'abord le pipeline sans la fin
| sh
afin de vérifier que la commande fait ce que vous voulez.Pour récurer plusieurs répertoires, utilisez quelque chose comme
Notez que dans sed, la séquence de regroupement des expressions régulières est constituée de crochets précédés d'une barre oblique inverse,
\(
et\)
, plutôt que de simples crochets(
et)
.la source
ls
dans les scripts. La première variété peut être obtenue avecprintf '%s\n' * | sed ...
et avec un peu de créativité, vous pouvez probablement vous en débarrassersed
. Bashprintf
propose un'%q'
code de format qui pourrait être utile si vous avez des noms de fichiers contenant des métacaractères shell littéraux.Je vais faire quelque chose comme ça:
supposé que tous vos fichiers sont dans le répertoire courant. Sinon, essayez d'utiliser find comme indiqué ci-dessus par Javier.
ÉDITER : De plus, cette version n'utilise aucune fonctionnalité spécifique à bash, comme d'autres ci-dessus, ce qui vous conduit à plus de portabilité.
la source
Voici un quasi-équivalent POSIX de la réponse actuellement acceptée . Cela échange l'
${variable/substring/replacement}
extension de paramètre uniquement Bash contre une extension disponible dans n'importe quel shell compatible Bourne.L'expansion des paramètres
${variable%pattern}
produit la valeur devariable
avec n'importe quel suffixe qui correspond àpattern
supprimé. (Il y a aussi${variable#pattern}
pour supprimer un préfixe.)J'ai gardé le sous-modèle
-[0-9.]*
de la réponse acceptée bien qu'il soit peut-être trompeur. Ce n'est pas une expression régulière, mais un modèle global; donc cela ne veut pas dire "un tiret suivi de zéro ou plusieurs nombres ou points". Au lieu de cela, cela signifie "un tiret, suivi d'un nombre ou d'un point, suivi de n'importe quoi". Le "n'importe quoi" sera le match le plus court possible, pas le plus long. (Bash propose##
et%%
pour couper le préfixe ou le suffixe le plus long possible, plutôt que le plus court.)la source
Nous pouvons supposer qu'il
sed
est disponible sur n'importe quel * nix, mais nous ne pouvons pas être sûrs qu'il prendra en charge lased -n
génération de commandes mv. ( REMARQUE: seul GNU lesed
fait.)Même ainsi, bash builtins et sed, nous pouvons rapidement créer une fonction shell pour ce faire.
Usage
Création de dossiers cibles:
Puisque
mv
ne crée pas automatiquement les dossiers cibles, nous ne pouvons pas utiliser notre version initiale desedrename
.C'est un changement assez petit, donc ce serait bien d'inclure cette fonctionnalité:
Nous aurons besoin d'une fonction utilitaire
abspath
(ou d'un chemin absolu) car bash n'a pas cette construction.Une fois que nous avons cela, nous pouvons générer le (s) dossier (s) cible (s) pour un modèle sed / rename qui inclut une nouvelle structure de dossier.
Cela garantira que nous connaissons les noms de nos dossiers cibles. Lorsque nous renommerons, nous devrons l'utiliser sur le nom du fichier cible.
Voici le script complet prenant en charge les dossiers ...
Bien sûr, cela fonctionne toujours lorsque nous n'avons pas non plus de dossiers cibles spécifiques.
Si nous voulions mettre toutes les chansons dans un dossier,
./Beethoven/
nous pouvons le faire:Usage
Tour bonus ...
Utilisation de ce script pour déplacer des fichiers de dossiers dans un seul dossier:
En supposant que nous voulions rassembler tous les fichiers correspondants et les placer dans le dossier actuel, nous pouvons le faire:
Remarque sur les modèles de regex sed
Les règles de modèle sed régulières s'appliquent dans ce script, ces modèles ne sont pas PCRE (Perl Compatible Regular Expressions). Vous pourriez avoir sed étendu la syntaxe des expressions régulières, en utilisant soit
sed -r
oused -E
fonction de votre plate-forme.Voir la compatibilité POSIX
man re_format
pour une description complète des modèles d'expression régulière sed basiques et étendus.la source
Je trouve que renommer est un outil beaucoup plus simple à utiliser pour ce genre de chose. Je l'ai trouvé sur Homebrew pour OSX
Pour votre exemple, je ferais:
Le «s» signifie substitut. Le formulaire est s / searchPattern / replacement / files_to_apply. Vous devez utiliser regex pour cela, ce qui demande un peu d'étude, mais cela en vaut la peine.
la source
for
etsed
etc. est bien, mais c'est beaucoup plus simple et plus rapide à utiliserrename
si vous vous trouvez souvent à le faire.rename
commande; en outre, certains auront une commande différenterename
avec des fonctionnalités, une syntaxe et / ou des options différentes. Cela ressemble au Perlrename
qui est assez populaire; mais la réponse devrait vraiment clarifier cela.meilleure utilisation
sed
pour cela, quelque chose comme:trouver l'expression régulière est laissé comme un exercice (comme c'est le cas avec les noms de fichiers qui incluent des espaces)
la source
Cela semble fonctionner en supposant que
enlevez le .pkg, puis enlevez - ..
la source
-e
. Par exemplesed -e 's/\.pkg//g' -e 's/-.*//g'
.ls
sortie et ne citez pas vos variables. Voir aussi shellcheck.net pour diagnostiquer les problèmes courants et les antipatterns dans les scripts shell.J'ai eu plusieurs
*.txt
fichiers à renommer comme.sql
dans le même dossier. ci-dessous a travaillé pour moi:la source
Merci pour ces réponses. J'ai aussi eu une sorte de problème. Déplacement des fichiers .nzb.queued vers des fichiers .nzb. Il y avait des espaces et d'autres cruels dans les noms de fichiers et cela a résolu mon problème:
Il est basé sur la réponse de Diomidis Spinellis.
L'expression régulière crée un groupe pour le nom de fichier entier et un groupe pour la partie avant .nzb.queued, puis crée une commande de déplacement du shell. Avec les chaînes entre guillemets. Cela évite également de créer une boucle dans le script shell car cela est déjà fait par sed.
la source
-n
option de la même manière.