Dis, j'ai un fichier foo.txt
spécifiant des N
arguments
arg1
arg2
...
argN
que je dois passer à la commande my_command
Comment utiliser les lignes d'un fichier comme arguments d'une commande?
Dis, j'ai un fichier foo.txt
spécifiant des N
arguments
arg1
arg2
...
argN
que je dois passer à la commande my_command
Comment utiliser les lignes d'un fichier comme arguments d'une commande?
Réponses:
Si votre shell est bash (entre autres), un raccourci pour
$(cat afile)
est$(< afile)
, donc vous écrirez:Documenté dans la page de manuel bash dans la section 'Command Substitution'.
Alternativement, faites lire votre commande à partir de stdin, donc:
mycommand < file.txt
la source
<
opérateur. Cela signifie que le shell lui-même effectuera la redirection plutôt que d'exécuter lecat
binaire pour ses propriétés de redirection."$(…)"
, le contenu defile.txt
serait passé à l'entrée standard demycommand
, pas en tant qu'argument."$(…)"
signifie exécuter la commande et restituer la sortie sous forme de chaîne ; ici la «commande» ne lit que le fichier mais cela pourrait être plus complexe.Comme déjà mentionné, vous pouvez utiliser les backticks ou
$(cat filename)
.Ce qui n'a pas été mentionné, et je pense qu'il est important de le noter, c'est que vous devez vous rappeler que le shell divisera le contenu de ce fichier selon des espaces, en donnant chaque "mot" qu'il trouve à votre commande comme argument. Et bien que vous puissiez mettre un argument de ligne de commande entre guillemets afin qu'il puisse contenir des espaces, des séquences d'échappement, etc., la lecture à partir du fichier ne fera pas la même chose. Par exemple, si votre fichier contient:
les arguments que vous obtiendrez sont:
Si vous souhaitez extraire chaque ligne comme argument, utilisez la construction while / read / do:
la source
read -r
moins que vous ne souhaitiez étendre les séquences d'échappement anti-slash - et NUL est un délimiteur plus sûr à utiliser que le saut de ligne, en particulier si les arguments que vous passez sont des choses comme des noms de fichiers, qui peuvent contenir des sauts de ligne littéraux. De plus, sans effacer IFS, les espaces de début et de fin sont supprimés implicitementi
.transmettra le contenu du fichier à la commande sur stdin, mais supprimera les nouvelles lignes, ce qui signifie que vous ne pouvez pas parcourir chaque ligne individuellement. Pour cela, vous pouvez écrire un script avec une boucle 'for':
Ou (la variante multiligne):
Ou (variante multiligne avec
$()
au lieu de``
):Références:
la source
< file
backticks signifie qu'il n'effectue pas du tout de redirectioncommand
.command `< file`
Ne fonctionne ni dans bash ni dans POSIX sh; zsh est une autre affaire, mais ce n'est pas le shell sur lequel porte cette question).Hello World
sur une ligne. Vous le verrez d'abord s'exécutersome_command Hello
, alorssome_command World
, passome_command "Hello World"
ousome_command Hello World
.Vous faites cela en utilisant des backticks:
la source
echo "Hello * Starry * World" > file.txt
dans la première étape, vous obtiendrez au moins quatre arguments séparés passés à la deuxième commande - et probablement plus, car le*
s s'étendrait aux noms des fichiers présents dans le répertoire courant.fork()
en dehors d'un sous-shell avec un FIFO attaché à son stdout, puis en l'appelant en/bin/cat
tant qu'enfant de ce sous-shell, puis en lisant la sortie via le FIFO; compare to$(<file.txt)
, qui lit le contenu du fichier dans bash directement sans sous-shell ou FIFO impliqué.Si vous souhaitez le faire d'une manière robuste qui fonctionne pour tous les arguments de ligne de commande possibles (valeurs avec espaces, valeurs avec sauts de ligne, valeurs avec guillemets littéraux, valeurs non imprimables, valeurs avec caractères glob, etc.), il obtient un peu plus intéressant.
Pour écrire dans un fichier, étant donné un tableau d'arguments:
... remplacer par
"argument one"
,"argument two"
, etc. , selon le cas.Pour lire ce fichier et utiliser son contenu (dans bash, ksh93 ou dans un autre shell récent avec des tableaux):
Pour lire à partir de ce fichier et utiliser son contenu (dans un shell sans tableaux; notez que cela écrasera votre liste d'arguments de ligne de commande locale, et qu'il est donc préférable de le faire à l'intérieur d'une fonction, de sorte que vous écrasiez les arguments de la fonction et non la liste globale):
Notez que
-d
(autoriser l'utilisation d'un délimiteur de fin de ligne différent) est une extension non POSIX, et un shell sans tableaux peut également ne pas la prendre en charge. Si tel est le cas, vous devrez peut-être utiliser un langage non-shell pour transformer le contenu délimité par NUL en uneeval
forme -safe:la source
Voici comment je passe le contenu d'un fichier comme argument à une commande:
la source
$(<bar.txt)
(lors de l'utilisation d'un shell, tel que bash, avec l'extension appropriée).$(<foo)
est un cas particulier: contrairement à la substitution de commandes régulière, telle qu'utilisée dans$(cat ...)
, elle ne crée pas un sous-shell pour fonctionner, et évite ainsi une surcharge importante.Si tout ce que vous avez à faire est de tourner le fichier
arguments.txt
avec le contenuen
my_command arg1 arg2 argN
vous pouvez simplement utiliserxargs
:Vous pouvez mettre des arguments statiques supplémentaires dans l'
xargs
appel, comme celuixargs -a arguments.txt my_command staticArg
qui appelleramy_command staticArg arg1 arg2 argN
la source
Dans ma coquille bash, ce qui suit a fonctionné comme un charme:
où input_file est
Comme évident, cela vous permet d'exécuter plusieurs commandes avec chaque ligne de input_file, une jolie petite astuce que j'ai apprise ici .
la source
$(somecommand)
, vous obtiendrez cette commande exécutée plutôt que transmise sous forme de texte. De même,>/etc/passwd
sera traité comme une redirection et un écrasement/etc/passwd
(si exécuté avec les autorisations appropriées), etc.xargs -d $'\n' sh -c 'for arg; do command1 "$arg"; command2 "arg"; command3 "arg"; done' _
- et aussi plus efficace, car il transmet autant d'arguments à chaque shell que possible plutôt que de démarrer un shell par ligne dans votre fichier d'entrée.cat
Après avoir édité la réponse de @Wesley Rice à quelques reprises, j'ai décidé que mes changements devenaient trop importants pour continuer à changer sa réponse au lieu d'écrire la mienne. Alors, j'ai décidé que je devais écrire le mien!
Lisez chaque ligne d'un fichier et opérez-la ligne par ligne comme ceci:
Cela vient directement de l'auteur Vivek Gite ici: https://www.cyberciti.biz/faq/unix-howto-read-line-by-line-from-file/ . Il en a le mérite!
Et maintenant pour répondre à cette question maintenant fermée que j'avais aussi: est-il possible de `git add` une liste de fichiers à partir d'un fichier? - voici ma réponse:
Notez qu'il
FILES_STAGED
s'agit d'une variable contenant le chemin absolu vers un fichier qui contient un tas de lignes où chaque ligne est un chemin relatif vers un fichier sur lequel j'aimerais fairegit add
. Cet extrait de code est sur le point de faire partie du fichier «eRCaGuy_dotfiles / useful_scripts / sync_git_repo_to_build_machine.sh» de ce projet, pour permettre une synchronisation facile des fichiers en développement d'un PC (ex: un ordinateur sur lequel je code) à un autre (ex: a ordinateur plus puissant sur lequel je construis): https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles .Références:
En relation:
git add
dessus: Est-il possible de `git add` une liste de fichiers à partir d'un fichier?la source