Comment faire remplacer plus dune sous-chaîne à la fois dans bash?

Jai un répertoire contenant des fichiers image qui doivent être repris dans bash. En écho, je souhaite remplacer à la fois le nom et lextension du fichier dans la commande sur une seule ligne.

Exemples de fichiers:

images/file_name_1.jpg images/file_name_2.jpg 

Normalement, je peux faire un remplacement simple comme ceci:

 for i in images/*; do echo ${i/file/image}; done  

Et le résultat devient comme:

 images/image_name_1.jpg images/image_name_2.jpg  

Comment puis-je le garder dans la boucle for et remplacer la chaîne « jpg » par « png » également? Cest juste une instance, je pourrais remplacer le point par une virgule, etc.

Quand jessaye ceci:

 for i in images/*; do echo ${{i/jpg/png}/file/image}; done  

Cela ne fonctionne pas. Je ne peux trouver aucune autre solution ou idée. Est-ce possible -si oui, comment?

Commentaires

  • Je ne ' Je ne sais pas pourquoi cela ' t fonctionne dans bash, mais les remplacements imbriqués fonctionnent exactement comme prévu dans zsh. En fonction de votre environnement, vous pouvez envisager d’utiliser un meilleur shell;)

Réponse

Lapproche simple serait dassigner le résultat à une variable, puis de travailler avec cette variable. Exemple:

 for filename in images/* do echo "filename is now $filename" filename=${filename/jpg/png}; echo "filename is now $filename" filename=${filename/file/image}; echo "filename is now $filename" echo "final filename is ${filename}" done  

Commentaires

  • Cette réponse nest pas complète. les substitutions sappliqueront nimporte où dans les chaînes du nom de fichier. En fonction de la question, Kubilay souhaite remplacer un préfixe et une extension (suffixe). pouvez-vous modifier et prendre cela en considération : $ {var / # Pattern / Replacement} Si le préfixe de var correspond à Pattern, remplacez le modèle par Replacement. $ {var /% Pattern / Replacement} Si suffixe de var correspond à Pattern, puis remplacez Replacement par Pattern.
  • @rMistero Il ny a ' aucune règle contre la publication dune autre réponse simplement parce quune réponse a été acceptée. En fait, je pense que vous devriez, dautant plus que la sémantique de ce que vous proposez est différente. Cela dit, cest la façon de faire ce que le PO a dit après avoir essayé, donc même sil y a dautres résultats qui pourraient également être valides, je pense quil est prudent de supposer que cela est conforme à ce que le PO voulait accomplir.

Réponse

Vous pouvez affecter le remplacement précédent à une variable et exécuter replace sur cette variable à la place

 for i in images/* do j=${i/jpg/png} echo ${j/file/image} done  

Commentaires

  • Incertain si ça marche. " pour i en images / *; faire j = {i / jpg / png} echo $ {j / fichier / image}; done " fait écho " {i / jpg / png} " à plusieurs reprises.
  • Maintenant oui: " pour i dans les images / *. jpg; faire j = $ {i / jpg / png}; echo $ {j / fichier / image}; terminé ". Merci!

Répondez

pour modifier nimporte quelle chaîne :

$ echo "images/file_name_1.jpg" | perl -pE "s/file/image/;s/jpg$/png/;" images/image_name_1.png 

un raccourci pour renommer (qui peut être le but ultime:

$ rename "s/file/image/;s/jpg$/png/;" "$i" 

Commentaires

  • Je pense toujours quinvoquer Perl une fois pour chaque fichier est excessif, mais au moins maintenant cela donne une réponse à la question. 🙂
  • @MichaelKj ö rling Vous navez ' pas besoin dappeler Perl pour chaque fichier, vous pouvez faire rename … images/*. Mais cela nécessite une distribution basée sur Debian (rename sur les autres variantes de Linux est une commande complètement différente).
  • @Gilles Je pensais plus à la première version, dautant plus quil ny a ' rien dans la question posée sur le changement de nom des fichiers. La version originale (période de grâce modifiée) de cette réponse ne contenait que la suggestion de commande rename.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *