Chcę tylko przenieść wszystkie pliki z określonego katalogu do tablicy bash (zakładając, że żaden z plików nie ma nowej linii w nazwie):
Więc:
myarr=()
find . -maxdepth 1 -name "mysqldump*" | mapfile -t myarr; echo "${myarr[@]}"
Pusty wynik!
Jeśli korzystam z pliku przy użyciu ronda, tymczasowo lub w inny sposób:
myarr=()
find . -maxdepth 1 -name "mysqldump*" > X
mapfile -t myarray < X
echo "${myarray[@]}"
Wynik!
Ale dlaczego nie mapfile
czyta poprawnie z potoku?
find
imapfile
tutaj, a nie tylkomyarr=(mysqldump*)
? Będzie to nawet działać z nazwami plików ze spacjami i znakami nowej linii.nullglob
opcję on (shopt -s nullglob
),myarr=(mysqldump*)
aby nie skończyć z tablicą('mysqldump*')
na wypadek, gdyby żadne pliki się nie zgadzały.Odpowiedzi:
Od
man 1 bash
:Takie podpowłoki dziedziczą zmienne z głównej powłoki, ale są one niezależne. Oznacza to, że
mapfile
w twoim oryginalnym poleceniu działa samodzielniemyarr
. Następnieecho
(będąc poza rurą) drukuje pustemyarr
(co jest główną powłokąmyarr
).To polecenie działa inaczej:
W tym przypadku
mapfile
iecho
działają na tym samymmyarr
(co nie jest głównym powłoka jestmyarr
).Aby zmienić główną powłokę,
myarr
musiszmapfile
dokładnie uruchomić ją w głównej. Przykład:źródło
Bash uruchamia polecenia potoku w środowisku podpowłoki, więc wszelkie przypisania zmiennych itp., Które mają miejsce w nim, nie są widoczne dla reszty powłoki.
Dash (Debian
/bin/sh
) i busyboxsh
są podobne, podczas gdy zsh i ksh uruchamiają ostatnią część w głównej powłoce. W Bash możeszshopt -s lastpipe
zrobić to samo, ale działa to tylko wtedy, gdy kontrola zadań jest wyłączona, więc domyślnie nie w interaktywnych powłokach.Więc:
(
read
imapfile
mają ten sam problem).Alternatywnie ( jak wspomniano w Attie) użyj substytucji procesu , która działa jak uogólniony potok i jest obsługiwana w Bash, ksh i zsh.
POSIX pozostawia nieokreślone, czy części potoku działają w podpowłokach, czy nie, więc nie można tak naprawdę powiedzieć, że żadna z powłok nie byłaby w tym „zła”.
źródło
set +m; shopt -s lastpipe; x=a; echo b | read x; echo $x; set -m
Jak zauważył Kamil, każdy element rurociągu jest osobnym procesem.
Można użyć następującego podstawienie proces dostać
find
do pracy w innym procesie, zmapfile
inwokacja pozostały w bieżącym tłumacza, umożliwiając dostęp domyarr
później:b < <( a )
będzie działał podobnie do tego,a | b
w jaki sposób okablowany jest rurociąg - różnica polega na tym, żeb
jest wykonywany „ tutaj ”.źródło