Je veux juste obtenir tous les fichiers d’un répertoire donné dans un tableau bash (en supposant qu’aucun des fichiers n’ait une nouvelle ligne dans le nom):
Alors:
myarr=()
find . -maxdepth 1 -name "mysqldump*" | mapfile -t myarr; echo "${myarr[@]}"
Résultat vide!
Si je fais la maniʻere détournée d'utiliser un fichier, temporaire ou non:
myarr=()
find . -maxdepth 1 -name "mysqldump*" > X
mapfile -t myarray < X
echo "${myarray[@]}"
Résultat!
Mais pourquoi ne mapfile
lit-il pas correctement à partir d'un tuyau?
find
etmapfile
ici du tout et pas simplementmyarr=(mysqldump*)
? Cela fonctionnera même avec les noms de fichiers avec des espaces et des nouvelles lignes.nullglob
option (shopt -s nullglob
) pourmyarr=(mysqldump*)
ne pas se retrouver avec le tableau('mysqldump*')
si aucun fichier ne correspond.Réponses:
De
man 1 bash
:Ces sous-shell héritent des variables du shell principal mais ils sont indépendants. Cela signifie que
mapfile
dans votre commande d'origine, elle fonctionne seulemyarr
. Ensuiteecho
(en dehors du tuyau) imprime videmyarr
(qui est celle du shell principalmyarr
).Cette commande fonctionne différemment:
Dans ce cas
mapfile
,echo
opérez de la même manièremyarr
(ce qui n'est pas le shell principalmyarr
).Pour changer le shell principal,
myarr
vous devez exécutermapfile
exactement le shell principal. Exemple:la source
Bash exécute les commandes d'un pipeline dans un environnement de sous-shell. Par conséquent, les affectations de variables, etc., qui y sont effectuées ne sont pas visibles pour le reste du shell.
Dash (Debian
/bin/sh
) et busyboxsh
sont similaires, alors que zsh et ksh exécutent la dernière partie du shell principal. Dans Bash, vous pouvezshopt -s lastpipe
faire de même, mais cela ne fonctionne que lorsque le contrôle du travail est désactivé, donc pas dans les shells interactifs par défaut.Alors:
(
read
etmapfile
ont le même problème.)Alternativement (et comme mentionné par Attie), utilisez la substitution de processus , qui fonctionne comme un tube généralisé et est prise en charge par Bash, ksh et zsh.
POSIX ne spécifie pas si les parties d'un pipeline sont exécutées dans des sous-coques ou non, donc on ne peut pas vraiment dire que l'une des coques serait "fausse".
la source
set +m; shopt -s lastpipe; x=a; echo b | read x; echo $x; set -m
Comme l'a souligné Kamil, chaque élément du pipeline est un processus distinct.
Vous pouvez utiliser ce qui suit la substitution de processus pour obtenir de
find
fonctionner dans un processus différent, avec l'mapfile
invocation qui reste dans votre interprète en cours, ce qui permet l' accès à lamyarr
suite:b < <( a )
agira de la même manièrea | b
en ce qui concerne la manière dont le pipeline est câblé - la différence est qu’ilb
est exécuté " ici ".la source