Takže udělat něco takového v bash a většina ostatních shellů nebude fungovat při vytváření více podadresářů nebo souborů v podadresářích…
mkdir */test
touch */hello.txt
Samozřejmě existuje mnoho způsobů, jak to skutečně udělat, já preferuji použití find pokud je to možné, místo použití for smyčka, hlavně kvůli čitelnosti.
Ale moje otázka zní, proč výše uvedené nefunguje?
Z toho, co jsem pochopil, je to proto, že úplný cílový soubor/cesta neexistuje, ale určitě je to dobrá věc, když se snažím mkdir nebo touch . Vždy jsem se jen posunul dál a nikdy jsem to nezpochybňoval.
Ale má pro to někdo slušné vysvětlení, které mi pomůže to jednou provždy pochopit?
Přijatá odpověď:
Bod, který vám možná uniká – se kterým má mnoho lidí potíže,
zvláště pokud mají zkušenosti s jinými operačními systémy, než přijdou na *nix
– je to, že v mnoha jiných operačních systémech jsou zástupné znaky na příkazového řádku se normálně předávají příkazu zpracovat, jak uzná za vhodné. Například v příkazovém řádku systému Windows
rename *.jpeg *.jpg
Zatímco v *nix, za účelem zjednodušení práce
programátorů jednotlivých příkazů (např. mv ), zástupné znaky
(pokud nejsou uvozovány nebo escapovány) zpracovává shell
způsobem, který je nezávislý na rozhraní a funkčnosti
příkazu, jehož jsou zástupné znaky argumenty.
Většina programů, které berou názvy souborů jako argumenty příkazového řádku, očekává existenci těchto souborů
(ano, mkdir a touch jsou výjimky z tohoto pravidla,
stejně jako mkfifo , mknod a v částečné míře cp , ln , mv a rename;
a pravděpodobně existují další),
, takže ve skutečnosti nemá smysl, aby shell rozšiřoval zástupné znaky
na názvy souborů, které neexistují.
A pro shell (a tím myslím každý shell –
Bourne, bash, csh, fish, ksh, zsh, atd...) zacházet s výjimkami jinak
by byl pravděpodobně příliš velký problém.
To znamená, že existuje několik způsobů, jak dosáhnout výsledku, jaký chcete.
Pokud víte, na co se zástupný znak rozšíří,
a není dlouhý, můžete jej vygenerovat pomocí rozšíření složené závorky:
touch {red,orange,yellow,green,blue,indigo,violet}/rgb.txt
Obecnější řešení:
sh -c 'for arg do mkdir -- "$arg"/test; done' -- *
Gilles mi pomohl najít jiný způsob
, jak to udělat v bash.
benbradley=(*)
mkdir "${benbradley[@]/%//test}"
Zřejmě benbradley je zde pouze identifikátor; můžete použít libovolné jméno
(např. libovolné písmeno).
Trvalo mi několik pokusů, než jsem to udělal správně, tak mi to dovolte rozebrat:
identifier=valuevytvoří (skalární) proměnnou s názvemidentifier(pokud již neexistuje) a přiřadí hodnotuvaluek tomu.
NapříkladG=Man.
Na skalární proměnnou můžete odkazovat pomocí$identifier;
například$G, nebo bezpečněji jako${identifier}.
Například$Gagea$Gillamůže být nedefinováno,
ale${G}agejeManagea${G}illajeManilla.identifier=(value1 value2 … )vytvoří proměnnou pole s názvemidentifier(pokud již neexistuje) a přiřadí mu uvedené hodnoty.
Například
spektrum=(červená oranžová žlutá zelená modrá indigová fialová)
nebo
all_text_files=(*.txt)
$name bude odkazovat na první prvek (a je tedy docela k ničemu).
Na libovolný prvek můžete odkazovat jako ${name[subscript]};
například ${spectrum[0]} je red a ${spectrum[4]} je blue .
A můžete použít ${name[@]} a ${name[*]} odkazovat na celé pole.
Takže tady je to po částech:
" ${ benbradley[@] / % / /test } " ${parameter/pattern/string}rozšiřuje${parameter}a nahradí nejdelší shodu
zpatternsstring.- Pokud
patternzačíná#,
musí se shodovat na začátku rozšířené hodnotyparameter.
Pokudpatternzačíná%,
musí se shodovat na konci rozšířené hodnotyparameter.
Jinými slovy,
chová se jako
(the-rest_of_the_regulex) $
(ano, to se zdá trochu obráceně).
Takže pattern to je jen % je jako regulární výraz, který je pouze $ –
odpovídá konci vstupního řetězce (vyhledávací mezera).
- A já používám
stringz/test.
Takže toto nahradí konec parametru/test(tj. připojí se/testna parametr). - Další věc o
${parameter/pattern/string}to není intuitivní, je to vždy končí}.
Nemusí a nemůže , končí třetím/.
Proto/vstringnelze interpretovat jako oddělovač,
a proto můžeme mítstringz/testaniž byste museli escapovat/. - Pokud
parameterje proměnná pole
s indexem@nebo*,
operace substituce se postupně aplikuje na každý člen pole. - Když na pole odkazujete jako
${name[@]}(spíše než${name[*]}) a výsledky vložte do dvojitých uvozovek,
zachováte integritu prvků pole
(tj. zachováte v nich mezery a další speciální znaky)
aniž byste jednotlivé prvky slučovali do jedno dlouhé slovo.