#1 Le 09/06/2020, à 11:02
- Xzu Rukneg
[résolu] créer un script simple pour traitement de fichier par lot
Bonjour.
J'ai beaucoup de fichiers texte (playlist) que je dois modifier.
J'ai deux actions à mener:
-changer un chemin par un autre
-changer une extension par une autre
Cela fonctionne très bien avec Gedit et la fonction rechercher/remplacer.
Mais j'aimerai maintenant automatiser la procédure par un script pour traiter en masse un dossier.
Merci si quelqu'un peut me montrer, je me noie dans les docs et apprends beaucoup mieux par l'exemple.
[edit] solution type:
sed -i -e 's%truc original1%truc modifié1%g' -e 's%\.extension1%.extension22%g' chemin/du/dossier/*.playlist
Dernière modification par Xzu Rukneg (Le 04/09/2020, à 14:33)
Hors ligne
#2 Le 09/06/2020, à 11:06
- kamaris
Re : [résolu] créer un script simple pour traitement de fichier par lot
Justement, il faudrait que tu donnes un exemple des modifications à réaliser !
Il n'y a probablement pas besoin d'un script : ça peut souvent se faire en une ligne avec sed ou awk.
Hors ligne
#3 Le 09/06/2020, à 14:43
- Xzu Rukneg
Re : [résolu] créer un script simple pour traitement de fichier par lot
Je recherche:
-machin/truc que je remplace par bidule/chouette
-.flac que je remplace par .ogg
Hors ligne
#4 Le 09/06/2020, à 14:58
- ptitjoz
Re : [résolu] créer un script simple pour traitement de fichier par lot
peut être avec la commande mv ?
mais il faut être prudent notamment si il y a des espaces dans tes noms de dossiers/fichiers.
par prudence tu peux faire des copies
Hors ligne
#5 Le 09/06/2020, à 15:02
- Xzu Rukneg
Re : [résolu] créer un script simple pour traitement de fichier par lot
J'ai beaucoup de fichiers texte (playlist) que je dois modifier
Je veux éditer le contenu des fichiers textes, qui sont des playlistes (fichier.playlist).
Hors ligne
#6 Le 09/06/2020, à 15:15
- ptitjoz
Re : [résolu] créer un script simple pour traitement de fichier par lot
ah ok j'ai mal lu désolé... oui peut-etre avec sed (duplique ton dossier pour faire tes essais)
peut etre ce lien ? https://fr.wikipedia.org/wiki/Stream_Editor
Hors ligne
#7 Le 09/06/2020, à 15:18
- DonutMan75
Re : [résolu] créer un script simple pour traitement de fichier par lot
Hello
y'a plein de gens ici beaucoup plus calés que moi avec sed mais je proposerais :
$ sed -r -i".bck" -e "s+machin/truc+bidule/chouette+g" -e "s/\.flac/\.ogg/g" *txt
-r : utilisation des regexp étendues (pas forcément utile ici mais j'ai l'habitude de toujours le mettre, je ne sais jamais si on doit échapper ou pas le "." par défaut)
-i".bck" : permet de créer un backup des fichiers (pratique si on veut éviter de faire une fausse manip..) si ça fonctionne bien on peut remplacer par -i sans argument pour écraser les fichiers en entrée
-e exécuter les commandes passées en argument, ici il y en a deux
Comme dit plus haut, il faudrait tout de même avoir un exemple de fichier type afin de vérifier qu'il n'y aura aucun effet de bord...
D.
Dernière modification par DonutMan75 (Le 09/06/2020, à 15:19)
Hors ligne
#8 Le 09/06/2020, à 17:27
- Xzu Rukneg
Re : [résolu] créer un script simple pour traitement de fichier par lot
Merci pour les détails. Les regexp ne sont pas encore dans mes concepts utilisés en pratique.
Pourquoi la syntaxe est-elle différente entre "s+machin/truc+bidule/chouette+g" et "s/\.flac/\.ogg/g"?
(+ dans un cas et / dans l'autre).
Comme dit plus haut, il faudrait tout de même avoir un exemple de fichier type afin de vérifier qu'il n'y aura aucun effet de bord...
Par précaution je suppose? C'est du fichier texte tout simple qui ne craint rien, facilement éditable.
Peut être que je ne comprends pas un truc mais ok voilà à quoi ça ressemble (playlist de exaile).
J'ai simplifié le nombre de ligne à cause des millions de caractères spéciaux et cie. Une ligne par fichier de playliste.
file:///home/machin/truc/fichier.flac
EOF
shuffle_mode=S: disabled
repeat_mode=S: disabled
dynamic_mode=S: disabled
current_position=I: -1
name=U: Dimimimi
Hors ligne
#9 Le 09/06/2020, à 19:14
- MicP
Re : [résolu] créer un script simple pour traitement de fichier par lot
Bonjour
Dans le contenu du fichier que tu donnes en exemple
il y a un caractère de tabulation (hexa 09) collé à la fin du nom d'extension.
Est-ce qu'il y a toujours ce caractère de tabulation à la fin du nom du fichier ?
michel@debT450:~$ printf '%s' "file:///home/machin/truc/fichier.flac " | hd
00000000 66 69 6c 65 3a 2f 2f 2f 68 6f 6d 65 2f 6d 61 63 |file:///home/mac|
00000010 68 69 6e 2f 74 72 75 63 2f 66 69 63 68 69 65 72 |hin/truc/fichier|
00000020 2e 66 6c 61 63 09 |.flac.|
00000026
michel@debT450:~$
Si NON, dans les lignes de commande sed il vaudrait mieux ajouter un caractère dollar après $ancienneExt dans les propositions ci-dessous.
=======
Pour ne remplacer que l'extension :
nomFichPlayListExaile="jeNeSaisPasQuelNom.listeExaile"
ancienneExt="flac"
nouvelleExt="ogg"
sed -i.sauv "/^file:\/\//s|$ancienneExt|$nouvelleExt|" $nomFichPlayListExaile
=======
Pour ne remplacer que le chemin :
nomFichPlayListExaile="jeNeSaisPasQuelNom.listeExaile"
ancienchemin="/home/machin/truc/"
nouveauchemin="/home/nouveauMachin/nouveauTruc/"
sed -i.sauv "/^file:\/\//|$ancienchemin|$nouveauchemin|" $nomFichPlayListExaile
=======
Pour remplacer le chemin ET l'extension :
nomFichPlayListExaile="jeNeSaisPasQuelNom.listeExaile"
ancienchemin="/home/machin/truc/"
nouveauchemin="/home/nouveauMachin/nouveauTruc/"
ancienneExt="flac"
nouvelleExt="ogg"
sed -i.sauv "/^file:\/\//s|$ancienneExt|$nouvelleExt|;|$ancienchemin|$nouveauchemin|" $nomFichPlayListExaile
=======
# Pour faire appliquer ça sur tous les fichiers dont le nom d'extension est .listeExaile
# et qui sont contenus dans /chemin/du/repertoire/ :
ancienchemin="/home/machin/truc/"
nouveauchemin="/home/nouveauMachin/nouveauTruc/"
ancienneExt="flac"
nouvelleExt="ogg"
shopt -s nullglob
for fich in /chemin/du/repertoire/*.listeExaile; do
sed -i.sauv "/^file:\/\//s|$ancienneExt|$nouvelleExt|;|$ancienchemin|$nouveauchemin|" "$fich"
done
=======
Note : -i.sauv c'est pour qu'une copie du fichier original soit sauvegardé (en y ajoutant l'extension ".sauv") avant la modification du fichier,
et on pourra plus tard, si tout s'est bien passé, supprimer tous les fichiers dont le nom d'extension est .sauv
Dernière modification par MicP (Le 09/06/2020, à 21:07)
Hors ligne
#10 Le 09/06/2020, à 19:23
- Watael
Re : [résolu] créer un script simple pour traitement de fichier par lot
avec l'option -s de sed, on devrait pouvoir se passer de la boucle.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#11 Le 09/06/2020, à 19:30
- MicP
Re : [résolu] créer un script simple pour traitement de fichier par lot
Cool
Ça donnerait simplement ça ? (je n'ai pas testé)
ancienchemin="/home/machin/truc/"
nouveauchemin="/home/nouveauMachin/nouveauTruc/"
ancienneExt="flac"
nouvelleExt="ogg"
shopt -s nullglob
sed -s -i.sauv "/^file:\/\//s|$ancienneExt|$nouvelleExt|;|$ancienchemin|$nouveauchemin|" /chemin/du/repertoire/*.listeExaile
Edit : Corrigé en fonction du message #13 de Watael
Dernière modification par MicP (Le 09/06/2020, à 21:01)
Hors ligne
#12 Le 09/06/2020, à 19:41
- DonutMan75
Re : [résolu] créer un script simple pour traitement de fichier par lot
Pourquoi la syntaxe est-elle différente entre "s+machin/truc+bidule/chouette+g" et "s/\.flac/\.ogg/g"?
(+ dans un cas et / dans l'autre).
Le + c'est pour ne pas avoir à échapper les "/" dans le chemin machin/truc
En gros, le premier caractère qui suit le s de substitute servira de délimiteur sed s+texte à modifier+texte modifié+
J'aurai pu mettre des + partout ceci dit :
$ sed -r -i".bck" -e "s+machin/truc+bidule/chouette+g" -e "s+\.flac+\.ogg+g" *txt
Hors ligne
#13 Le 09/06/2020, à 20:17
- Watael
Re : [résolu] créer un script simple pour traitement de fichier par lot
@MicP : il ne faut pas mettre le chemin entre guillemets, sinon l'astérisque ne sera pas développé.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#14 Le 09/06/2020, à 20:59
- MicP
Re : [résolu] créer un script simple pour traitement de fichier par lot
il ne faut pas mettre le chemin entre guillemets, sinon l'astérisque ne sera pas développé.
Ok, merci
Je corrige mon précédent message de suite.
Dernière modification par MicP (Le 09/06/2020, à 21:01)
Hors ligne
#15 Le 13/06/2020, à 12:36
- Xzu Rukneg
Re : [résolu] créer un script simple pour traitement de fichier par lot
Merci tout le monde.
Sympa ce sed.
Si je reprends la commandes proposé par Donutman, il faut que je me place dans le dossier contenant mes fichiers à modifier pour y exécuter la commande? Je tiens à pouvoir cibler un dossier.
L'extension des fichiers est .playlist, et j'ai créé un dossier back dans /.local/share/exaile/playlists/ pour ne pas être embêté.donc:
$ sed -i"~/.local/share/exaile/playlists/back/.bck" -e "s+machin/truc+bidule/chouette+g" -e "s+\.flac+\.ogg+g" *.playlist
Est-ce ok?
@Micp: je ne suis pas sur, ce que tu propose et à mettre dans un script, c'est bien ça?
Et oui pour la tabulation, pas forcément en fin de ligne mais après le chemin du fichier audio.
Ça peut même aller jusqu'à:
fichier.flac album=Rythm+in+mind&title=Left+Of+Center+&artist=Steve+Coleman&date=19&genre=A+Cappella&tracknumber=2
Il peut manquer des paramètres (genre,etc..) sans que ça gène.
Hors ligne
#16 Le 13/06/2020, à 13:22
- kamaris
Re : [résolu] créer un script simple pour traitement de fichier par lot
Si je reprends la commandes proposé par Donutman, il faut que je me place dans le dossier contenant mes fichiers à modifier pour y exécuter la commande?
Non, et c'est même mieux de ne pas se déplacer pour rien :
sed [options-sed] 'programme-sed' /chemin-vers-fichiers/*.playlist
Est-ce ok?
Non, l'option -i attend une extension à ajouter au nom de fichier original, pas un chemin pour une copie.
Si tu veux faire ça, il faut faire la copie avant ou après toi-même :
cp /chemin-original/fichier-original /chemin-de-sauvegarde/fichier-original.bck && sed …
ou
sed -i.bck … && cp /chemin-original/fichier-original.bck /chemin-de-sauvegarde/
Hors ligne
#17 Le 13/06/2020, à 15:21
- Xzu Rukneg
Re : [résolu] créer un script simple pour traitement de fichier par lot
Ok.L'option -i n'est pas pratique dans mon cas.
Je doit selectionner les fichiers de toutes façons, je les copie donc dans un dossier /test.
J'ai testé la commande (j'ai fait mon backup donc pas de soucis), et j'ai 1 millions de lignes en sorties.
Je test alors sur un fichier zob.playlist dans ~/.local/share/exaile/playlists/test/ qui contient uniquement:
zu/Bureau/
Je test donc:
:~$ sed -e "s+zu/Bureau/+16/Bureau/AUDIO/+g" ~/.local/share/exaile/playlists/test/zob.playlist
16/Bureau/AUDIO/
Rien n'a changé dans le fichier.
Pourquoi indique-t-il 16/Bureau/AUDIO/ en sortie?
J'ai re-consulté le liens de ptitjoz et me suis demandé si sed n'attendais pas un nom de fichier de sortie.
Je commence à croire que si parceque cette commande fonctionne:
sed -e "s+zu/Bureau/+16/Bureau/AUDIO/+g" ~/.local/share/exaile/playlists/test/zob.playlist > ~/.local/share/exaile/playlists/test/zob2.playlist
Et elle ne donne pas de message en sortie.
Donc j'ai trouvé quelque chose qui marche mais j'aimerai quand même pouvoir écraser directement le contenu, sans avoir à indiquer un nom de fichier de sortie. De plus je ne sais pas ce que ça donnerai pour un lot de fichiers (mon but reste de traiter tout un dossier de fichiers).
Autre question: pourquoi y a-t-il des anti-slash dans -e "s+\.flac+\.ogg+g" ?
Hors ligne
#18 Le 13/06/2020, à 15:38
- kamaris
Re : [résolu] créer un script simple pour traitement de fichier par lot
sed, comme la plupart des commandes et en tout cas des filtres, écrit sur la sortie standard.
Ça permet de passer facilement sa sortie à une autre commande si on le souhaite :
sed [options-sed] 'programme-sed' fichier-d-entrée | autre-commande …
Donc si on veut que la sortie de sed aille dans un fichier, il faut effectivement rediriger cette sortie.
C'est ce que fait l'opérateur > dans ta dernière commande ci-dessus.
Ou bien, il faut utiliser l'option -i pour éditer directement le fichier d'entrée.
Pour une édition par lot, il suffit de conjuguer l'option -i avec le développement de chemins par le shell :
sed -i 'programme-sed' /chemin-vers-fichiers/*.playlist
Les antislashs servent à protéger les points d'une interprétation en tant que caractère spécial dans une expression régulière, où ils signifient « n'importe quel caractère ».
Ils ne sont d'ailleurs nécessaires que dans la partie gauche de la commande s de sed : -e "s+\.flac+.ogg+g"
Hors ligne
#19 Le 02/08/2020, à 14:13
- Xzu Rukneg
Re : [résolu] créer un script simple pour traitement de fichier par lot
Ou bien, il faut utiliser l'option -i pour éditer directement le fichier d'entrée.
Merci pour cette reprécisions, j'ai pu m'en sortir.
Donc l'option -i sert à plusieurs choses, c'est ce qui m'a perdu. Typiquement le genre de truc sur lequel je ne m'en serai pas sortie sans vous! Merci!
Solution:
Au final je tourne avec un
sed -i -e "s+\truc original1+truc modifié1+g" -e "s+\truc original2+truc modifié2+g" chemin/du/dossier/*playlist
Je me suis copié à part les séquences de -e "s+\truc original+truc modifié+g" au cas où.
Et je gère les back, écrasage et cie manuellement, c'est vite fait et bien sécure!
J'ai du reprendre une édition suite à une erreur (un caractère en trop, le -),
sed -i -e "s+\16/Bureau/AUDIO/-+16/Bureau/AUDIO/+g"
et j'ai du enlever le \ sinon j'avais ce message:
sed: -e expression n°1, caractère 39: Référence arrière invalide
le \ étant sur le caractère 14 je n'ai compris, mais bref cela ne m'a pas bloqué.
Merci beaucoup et désolé pour le silence!
Dernière modification par Xzu Rukneg (Le 02/08/2020, à 15:03)
Hors ligne
#20 Le 02/08/2020, à 17:48
- kamaris
Re : [résolu] créer un script simple pour traitement de fichier par lot
Utiliser + comme séparateur pour la commande s de sed n'est pas forcément une bonne idée, car il s'agit d'un caractère spécial en expressions régulières (précédé ou non d'un antislash selon qu'on fait des regex basiques ou étendues).
Tu as l'embarras du choix pour le séparateur, donc utilise plutôt % ou @ ou autre chose d'adapté à la situation…
Pour l'antislash, il faut le doubler pour qu'il soit considéré littéralement, en utilisant des guillemets simples (les antislashs sont interprétés par le shell dans des guillemets doubles, ce qui complique encore les choses) :
sed -i -e 's%\\16/Bureau/AUDIO/-%\\16/Bureau/AUDIO/%g'
Mais est-ce bien ce que tu veux ?
Je pense que ta première commande devrait plutôt être :
sed -i -e 's%truc original1%truc modifié1%g' -e 's%truc original2%truc modifié2%g' chemin/du/dossier/*playlist
car sinon le \t correspond à un caractère de tabulation…
Dernière modification par kamaris (Le 02/08/2020, à 18:19)
Hors ligne
#21 Le 03/08/2020, à 11:59
- Xzu Rukneg
Re : [résolu] créer un script simple pour traitement de fichier par lot
Salut.
Ok pour le +, va pour % ou @.
Pour le reste, moins. J'utilisais l'antislash en référence à ton message #18 -e "s+\.flac+.ogg+g".
Hors ligne
#22 Le 03/08/2020, à 12:07
- kamaris
Re : [résolu] créer un script simple pour traitement de fichier par lot
Mais dans mon message #18, je dis bien que l'antislash sert à protéger le point (« . ») d'une interprétation en tant que caractère spécial, c'est-à-dire à faire en sorte qu'il soit considéré littéralement.
Dans ce que tu écris en #19, il n'y a pas de caractère spécial à protéger (ou alors il faut préciser le contenu de « truc original1 » et « truc original2 »).
Donc l'antislash est au mieux inutile, au pire il change le sens de l'expression régulière, selon les cas…
Dernière modification par kamaris (Le 03/08/2020, à 12:09)
Hors ligne
#23 Le 05/08/2020, à 23:45
- Xzu Rukneg
Re : [résolu] créer un script simple pour traitement de fichier par lot
Merci pour le suivis!
Ok, mauvaise compréhension de "considéré littéralement" de ma part, à propos du \.
Non je ne veux pas qu'il soit considéré littéralement, je comprends mieux pourquoi tu me demandais ça du coup.
Je voulais juste le mettre en protection, en prévention. D'après ce que je comprends c'est pas une bonne idée si il n'est pas nécessaire, c'est plus compliqué que ça.
Donc dit moi si je me trompe:
- le \ est nécessaire pour rechercher .flac au lieu de flac, ce qui explique pourquoi ça fonctionnerait aussi sans. Vaut donc mieux le laisser pour cette commande ci.
Q:
- c'est quoi ce message d'erreur sur le caractère 39? (#19) pige pas.
- y aurait-il d'autres caractère à protéger que le point ? comment savoir?
- le "\t qui correspond à un caractère de tabulation", c'est bien à cause de l'interprétation du shell à cause des guillemets doubles?
REM: C'est quand même pas si simple cette histoire juste pour du rechercher/remplacer!
Je veux dire par là que c'est faisable très simplement avec un éditeur, sans aucune connaissance mais juste un peu de logique.
Mais voilà que je veux faire ça "en lot", ce qui est une des fonctions initiale d'un ordi (faire tous les trucs répétitifs), et je me retrouve embarqué dans un truc d'une toute autre complexité, je ne m'attendais quand même pas à ça!
On est bien d'accord qu'il n'y a pas à priori d'outils tout simple pour ça? (pas trouvé en tous cas)
Hors ligne
#24 Le 06/08/2020, à 00:53
- beuguissime
Re : [résolu] créer un script simple pour traitement de fichier par lot
Bonsoir,
Dans une expression régulière, le symbole point désigne un caractère, quel qu'il soit. Donc l'expression régulière suivante
a.c
pourra correspondre à
abc
a1c
etc, mais aussi à
a.c
(où là il s'agit d'un véritable point dans le texte analysé).
C'est un caractère joker, si tu veux, qui est très pratique quand par exemple, on sait qu'il y aura un caractère à tel endroit de la chaîne mais dont on ne connaît pas précisément la nature.
Si, maintenant, tu sais que le premier caractère de la chaîne à remplacer est un point, alors il faut l'échapper avec le symbole contre-oblique \ pour que sed l'interprète comme un point au sens littéral et non pas comme un joker comme exposé ci-dessus.
Dans ton cas, il y a de grandes chances que .flac ou \.flac reviennent au même mais il faut garder en tête que .flac est plus permissif que \.flac.
Si une de tes chansons s'intitule
Le flacon brisé.flac
alors avec \.flac tu ne remplaceras que l'extension mais avec .flac tu remplaceras aussi “ flac” (c'est-à-dire l'espace après Le et le début du mot flacon - ce n'est pas ce que tu souhaites). Pour t'en rendre compte, tu peux taper ceci dans une console
$ echo "Le flacon brisé.flac" | sed 's/\.flac/.ogg/g'
Le flacon brisé.ogg
$ echo "Le flacon brisé.flac" | sed 's/.flac/.ogg/g'
Le.oggon brisé.ogg
Note qu'il n'est pas nécessaire d'échapper le point dans la deuxième partie de l'instruction sed.
Hors ligne
#25 Le 06/08/2020, à 04:30
- MicP
Re : [résolu] créer un script simple pour traitement de fichier par lot
Bonjour
Ou alors, tu précise, en ajoutant le caractère $
que c'est seulement la suite flac qui est en fin de ligne qu'il faudra remplacer
$ echo "Le flacon brisé.flac" | sed 's/flac$/ogg/g'
Le flacon brisé.ogg
Hors ligne