BASH traitement sur l'ensemble des arguments
Fermé
gnugo
-
20 janv. 2012 à 15:49
dubcek Messages postés 18758 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 24 décembre 2024 - 25 janv. 2012 à 08:01
dubcek Messages postés 18758 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 24 décembre 2024 - 25 janv. 2012 à 08:01
A voir également:
- Arguments bash
- Bingo bash free - Télécharger - Divers Jeux
- Bash permission non accordée - Forum Shell
- Retour à la ligne bash ✓ - Forum Shell
- Bash écrire dans un fichier - Forum Shell
- Bash addition ✓ - Forum Shell
16 réponses
dubcek
Messages postés
18758
Date d'inscription
lundi 15 janvier 2007
Statut
Contributeur
Dernière intervention
24 décembre 2024
5 623
Modifié par dubcek le 20/01/2012 à 16:03
Modifié par dubcek le 20/01/2012 à 16:03
hello
en changeant IFS et avec des ", on peut avoir un autre caractère qu'espace comme séparateur
en changeant IFS et avec des ", on peut avoir un autre caractère qu'espace comme séparateur
$ set "a 1" "b 2" "c 3" $ echo $* a 1 b 2 c 3 $ echo "$*" a 1 b 2 c 3 $ IFS=";" $ echo "$*" a 1;b 2;c 3 $
Merci,
ça répond vraiment bien à ce que je cherche, je peux alors travailler avec $* sans soucis, mais...
maintenant il me faut trouver bon séparateur.
Mes paramètres sont des noms de fichiers, pourrais-tu me dire s'il y a un caractère ne pouvant pas faire parti des noms de fichiers, que je pourrais utiliser ?
ça répond vraiment bien à ce que je cherche, je peux alors travailler avec $* sans soucis, mais...
maintenant il me faut trouver bon séparateur.
Mes paramètres sont des noms de fichiers, pourrais-tu me dire s'il y a un caractère ne pouvant pas faire parti des noms de fichiers, que je pourrais utiliser ?
dubcek
Messages postés
18758
Date d'inscription
lundi 15 janvier 2007
Statut
Contributeur
Dernière intervention
24 décembre 2024
5 623
20 janv. 2012 à 16:39
20 janv. 2012 à 16:39
tout les caractères sont autorisés dans les noms, mais je dirais:
; puisque c'est un séparateur de commande, # commentaires, etc
; puisque c'est un séparateur de commande, # commentaires, etc
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Oui mais si j'ai un fichier avec un de ces caractères qui sont autorisés, ça ne marchera pas
Ce serait une faille dans mon script que de faire un truc pareil.
Du coup je ne vois pas comment faire... à part en me débrouillant en itérant dans une boucle pour reconstruire ma variable, mais c'est justement pour éviter de faire ça que je suis venu chercher de l'aide.
$@ arrive bien à les séparer pourtant, il fait comment lui ?
Ce serait une faille dans mon script que de faire un truc pareil.
Du coup je ne vois pas comment faire... à part en me débrouillant en itérant dans une boucle pour reconstruire ma variable, mais c'est justement pour éviter de faire ça que je suis venu chercher de l'aide.
$@ arrive bien à les séparer pourtant, il fait comment lui ?
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 419
20 janv. 2012 à 16:51
20 janv. 2012 à 16:51
Salut,
je ne souhaite pas itérer sur chaque argument, mais appliquer un traitement sur "l'ensemble de mes arguments", traitement incluant des espaces et des sauts de lignes.
Pour aller plus vite et gagner du temps :
Quels traitements comptes-tu faire ?
De quelles façons ?
je ne souhaite pas itérer sur chaque argument, mais appliquer un traitement sur "l'ensemble de mes arguments", traitement incluant des espaces et des sauts de lignes.
Pour aller plus vite et gagner du temps :
Quels traitements comptes-tu faire ?
De quelles façons ?
dubcek
Messages postés
18758
Date d'inscription
lundi 15 janvier 2007
Statut
Contributeur
Dernière intervention
24 décembre 2024
5 623
Modifié par dubcek le 20/01/2012 à 16:59
Modifié par dubcek le 20/01/2012 à 16:59
$@ affiche l'ensemble des $1, $2, etc
tester si le caractère est présent dans $*, si oui en prendre un autre
tester si le caractère est présent dans $*, si oui en prendre un autre
$ set "a 1" "b 2" "c;3" $ $ echo "$*" a 1 b 2 c;3 $ $ grep -q ";" <<<"$*" $ echo $? 0 $ $ IFS="#" # on utilise # et pas ; $ $ echo "$*" a 1#b 2#c;3 $ $
-->Réponse à zipe31 :
Bah en fait peu importe le traitement, je sais que je pourrai éventuellement le faire avec une boucle mais ce n'est pas cette solution que je cherche, même si elle fonctionnerait parfaitement.
Pour simplifier au maximum, disons que j'ai en arguments des noms de fichiers
Et je souhaite en faire une liste dans une seule variable qui contiendra alors tous mes noms de fichiers séparés par un caractère.
Ensuite, je passe cette liste à un programme exécutable qui lui effectuera le traitement.
Mais je ne trouve pas comment séparer mes noms de fichiers puisque tous les caractères peuvent être utilisés.
Pourtant je constate que dans $@ ils semblent correctement séparés, donc ça doit être possible.
J'espère être suffisamment clair. N'hésitez pas à me poser des questions si ça ne l'est pas.
Et encore merci
-->À ducek :
Intéressant mais si dans mes arguments j'ai tous les caractères possibles de noms de fichiers, ce qui est possible, le script ne peut plus rien faire,non?
Cette façon de faire à l'air en plus très compliquée, tester tous les caractères possibles pour en trouver un de libre...ça fait beaucoup
En mettant directement Le séparateur qu'il faut (celui de $@ peut être?) ça sera quand même beaucoup plus simple et efficace
Bah en fait peu importe le traitement, je sais que je pourrai éventuellement le faire avec une boucle mais ce n'est pas cette solution que je cherche, même si elle fonctionnerait parfaitement.
Pour simplifier au maximum, disons que j'ai en arguments des noms de fichiers
Et je souhaite en faire une liste dans une seule variable qui contiendra alors tous mes noms de fichiers séparés par un caractère.
Ensuite, je passe cette liste à un programme exécutable qui lui effectuera le traitement.
Mais je ne trouve pas comment séparer mes noms de fichiers puisque tous les caractères peuvent être utilisés.
Pourtant je constate que dans $@ ils semblent correctement séparés, donc ça doit être possible.
J'espère être suffisamment clair. N'hésitez pas à me poser des questions si ça ne l'est pas.
Et encore merci
-->À ducek :
Intéressant mais si dans mes arguments j'ai tous les caractères possibles de noms de fichiers, ce qui est possible, le script ne peut plus rien faire,non?
Cette façon de faire à l'air en plus très compliquée, tester tous les caractères possibles pour en trouver un de libre...ça fait beaucoup
En mettant directement Le séparateur qu'il faut (celui de $@ peut être?) ça sera quand même beaucoup plus simple et efficace
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 419
20 janv. 2012 à 17:27
20 janv. 2012 à 17:27
Normalement le traitement de "$@" (guillemets compris) devrait faire l'affaire.
;-))
$ cat plop Salut $ cat mon\ fich bonjour $ set plop "mon fich" $ cat $@ Salut cat: mon: Aucun fichier ou dossier de ce type cat: fich: Aucun fichier ou dossier de ce type $ cat "$@" Salut bonjour $
;-))
zipe31
Messages postés
36402
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 419
20 janv. 2012 à 18:07
20 janv. 2012 à 18:07
Mais alors pour en finir, les noms sont séparés avec quoi dans "$@" ?
Par un caractère null.
Par un caractère null.
Rebonsoir,
Alors j'ai un peu creusé là dessus et mon traitement fonctionne parfaitement si je sépare mes fichiers par le caractère NUL ( '\0' )
J'ai pu faire les tests grâce à l'option -print0 de find qui me sépare bien les fichiers avec un '\0'
Maintenant il faut juste que je fasse la même chose sans find
Comment mettre sur la sortie de mon script la liste de ses arguments séparés par ce caractère ?
En effet, je dois passer cette liste à l'entrée standard de mon programme de traitement
J'ai essayé des choses comme : ./traitement <<<"$@" mais pas concluant
(Je suis ouvert à toute suggestion cette fois :] )
Alors j'ai un peu creusé là dessus et mon traitement fonctionne parfaitement si je sépare mes fichiers par le caractère NUL ( '\0' )
J'ai pu faire les tests grâce à l'option -print0 de find qui me sépare bien les fichiers avec un '\0'
Maintenant il faut juste que je fasse la même chose sans find
Comment mettre sur la sortie de mon script la liste de ses arguments séparés par ce caractère ?
En effet, je dois passer cette liste à l'entrée standard de mon programme de traitement
J'ai essayé des choses comme : ./traitement <<<"$@" mais pas concluant
(Je suis ouvert à toute suggestion cette fois :] )
Utilisateur anonyme
20 janv. 2012 à 18:59
20 janv. 2012 à 18:59
salut,
bash ne sait pas manipuler le caractère NULL.
pourquoi pas une boucle ?
pourquoi pas find ?
bash ne sait pas manipuler le caractère NULL.
pourquoi pas une boucle ?
pourquoi pas find ?
Je veux bien faire une boucle si au final j'obtiens ma liste
Quelque chose comme
Conviendrait parfaitement.
Et find ne convient pas car je ne souhaite traiter qu'une liste de fichiers précis.
./script fic1 file5 "aaa bb" | traitement
find recherche des fichiers. dans mon cas je connais déjà les fichiers que je veux traiter. Find peut prendre ma liste et me la renvoyer au bon format avec print0 ?
Quelque chose comme
for f in "$@" do liste="$liste\0$f" done
Conviendrait parfaitement.
Et find ne convient pas car je ne souhaite traiter qu'une liste de fichiers précis.
./script fic1 file5 "aaa bb" | traitement
find recherche des fichiers. dans mon cas je connais déjà les fichiers que je veux traiter. Find peut prendre ma liste et me la renvoyer au bon format avec print0 ?
Bon alors pour l'instant j'ai fait ça :
for f in "$@"
do
echo -n "$f"
echo -ne "\0"
done | traitement
Ça marche, mais c'est pas terrible je trouve, surtout quand on pense que "$@" est déjà au bon format.
Voilà. Qu'en pensez-vous? Comment auriez-vous fait ?
for f in "$@"
do
echo -n "$f"
echo -ne "\0"
done | traitement
Ça marche, mais c'est pas terrible je trouve, surtout quand on pense que "$@" est déjà au bon format.
Voilà. Qu'en pensez-vous? Comment auriez-vous fait ?
Utilisateur anonyme
20 janv. 2012 à 19:48
20 janv. 2012 à 19:48
ah, j'ai oublié : pourquoi «./traitement <<<"$@" [...] pas concluant » ?
$ premiere() { deuxieme "$@";} $ deuxieme() { printf '%s\n' "$@";} $ premiere foo bar "bar baz" foo bar bar bazlà, c'est des fonctions, mais ce serait pareil avec des scripts.
Non c'est justement ce qu'il faisait au départ.
Mais parfois le traitement est amené a travailler sur un grand nombre de fichiers, Et quand il y a trop de noms j'ai une erreur "argument line too long"
Voilà pourquoi je cherche maintenant à faire passer cette liste sur l'entrée standard. Comme ça , pas de limite, plus de problème
Mais parfois le traitement est amené a travailler sur un grand nombre de fichiers, Et quand il y a trop de noms j'ai une erreur "argument line too long"
Voilà pourquoi je cherche maintenant à faire passer cette liste sur l'entrée standard. Comme ça , pas de limite, plus de problème
Bah je vois pas ou est le problème je pense avoir donné tous les détails
Je n'ai plus le script ni le prog de traitement sous les yeux
Si vous voulez tester le même comportement:
#Version avec lecture de l'entrée standard
for f in "$@"
do
echo -n "$f"
echo -ne "\0"
done | ssh 127.0.0.1 cat
#Version utilisant les paramètres
ssh 127.0.0.1 "echo \"$@\""
Les 2 fonctionnent mais... faites le test avec 4000 noms de fichiers dans "$@" , vous verrez une belle erreur too many arguments
Si vous avez une solution pour éviter le pb tout en conservant le fonctionnement par arguments, je suis ouvert
Mais à mon avis avec une liste de fichiers pouvant atteindre une grosse taille, un traitement par flux dans l'entrée standard c'est mieux que la ligne de commande limitée
Je n'ai plus le script ni le prog de traitement sous les yeux
Si vous voulez tester le même comportement:
#Version avec lecture de l'entrée standard
for f in "$@"
do
echo -n "$f"
echo -ne "\0"
done | ssh 127.0.0.1 cat
#Version utilisant les paramètres
ssh 127.0.0.1 "echo \"$@\""
Les 2 fonctionnent mais... faites le test avec 4000 noms de fichiers dans "$@" , vous verrez une belle erreur too many arguments
Si vous avez une solution pour éviter le pb tout en conservant le fonctionnement par arguments, je suis ouvert
Mais à mon avis avec une liste de fichiers pouvant atteindre une grosse taille, un traitement par flux dans l'entrée standard c'est mieux que la ligne de commande limitée
J'ai une autre interrogation sur le même sujet :
Est-il possible de récupérer avec la commande ls une liste de fichiers pour la traiter en arguments ?
C'est à dire : "./script $(ls)" pour obtenir la liste des fichiers dans la liste des arguments "$@" du script.
Ça ne marche pas avec un fichier contenant un espace, il pense qu'il y a 2 fichiers. "aa bb" donne "aa" et "bb" dans "$@"
En faisant ./script "$(ls)" c'est pire, il considère toute la liste de fichiers comme un seul
Est-il possible de récupérer avec la commande ls une liste de fichiers pour la traiter en arguments ?
C'est à dire : "./script $(ls)" pour obtenir la liste des fichiers dans la liste des arguments "$@" du script.
Ça ne marche pas avec un fichier contenant un espace, il pense qu'il y a 2 fichiers. "aa bb" donne "aa" et "bb" dans "$@"
En faisant ./script "$(ls)" c'est pire, il considère toute la liste de fichiers comme un seul
dubcek
Messages postés
18758
Date d'inscription
lundi 15 janvier 2007
Statut
Contributeur
Dernière intervention
24 décembre 2024
5 623
23 janv. 2012 à 11:21
23 janv. 2012 à 11:21
essayer
$ IFS=$'\n' ; ./script $(ls -1) # ou $ ./script *
Utilisateur anonyme
23 janv. 2012 à 11:13
23 janv. 2012 à 11:13
normalement
./script *devrait traiter tous les fichiers du répertoire courant
Effectivement le IFS=$'\n' ; peut être une bonne solution mais il le problème c'est qu'il faudra le taper à chaque fois, on ne peut pas l'automatiser ou le mettre dans le script car la "transformation" du retour du 'ls' et même le ls lui même qui renvoie un mauvais résultat(\n séparateur) se fait en amont. (ls sépare par des \n alors que c'est un caractère possible pour les noms de fichiers...dommage). Donc soit je l'utilise et je fais avec son résultat sachant à quoi m'en tenir, soit je ne l'utilise pas.
En tout cas mon souci premier est résolu et je vous remercie pour votre aide !
Merci
En tout cas mon souci premier est résolu et je vous remercie pour votre aide !
Merci
dubcek
Messages postés
18758
Date d'inscription
lundi 15 janvier 2007
Statut
Contributeur
Dernière intervention
24 décembre 2024
5 623
25 janv. 2012 à 08:01
25 janv. 2012 à 08:01
l'option -print0 de la commande find remplace le \n par \0 après chaque nom de fichier
$ find . -maxdepth 1 -print0