Pomocí bash nastavte nastavení glob tak, aby chybějící shody nezpůsobily chybu:
shopt -u failglob # avoid failure report (and discarding the whole line).
shopt -s nullglob # remove (erase) non-matching globs.
ls ?c c?
Otazník je znak glob představující jeden znak. Protože chcete dvouznakové názvy souborů, jeden z nich musí být c
, a je to buď první znak, nebo poslední znak.
S shopt -s dotglob
tím by se také objevil soubor s názvem .c
.
Pokud neexistují žádné odpovídající soubory, nastavení těchto možností shellu způsobí odstranění všech argumentů, což má za následek holý ls
-- výchozí seznam čehokoli/všeho.
Místo toho použijte toto:
shopt -s nullglob ## drop any missing globs
set -- ?c c? ## populate the [email protected] array with (any) matches
if [ $# -gt 0 ] ## if there are some, list them
ls -d "[email protected]"
fi
Myslím, že lepší způsob je použít find
:
find . -type f -name '*c*' -name '??'
To bude hledat rekurzivně. Chcete-li zobrazit pouze soubory v aktuálním adresáři:
find . ! -name . -prune -type f -name '*c*' -name '??'
Pokud soubory existují (a neobsahují žádné speciální znaky jako \c
), můžete použít glob:
echo ?c c?
které budou odpovídat souborům, které mají jeden znak (?
) následovaný c
nebo které mají c
následovaný jedním znakem (?
).
Ale selže s názvy souborů které začínají pomlčkou jako -n
nebo -e
nebo se znaky zpětného lomítka jako \c
nebo \n
s echo
jako oba -e
a -n
jsou speciální pro (některé shelly) echo
a \c
nebo \n
by bylo interpretováno jako escape sekvence (\c
ukončí výstup a \n
vytiskne nový řádek, nikoli doslovné znaky \n
v nějaké implementaci shellu echo a bash, když je volba shopt -s xpg_echo
je nastaveno). Jiné aplikace nebo nástroje (jako ls
) bude mít některé další možnosti a může selhat u mnoha dalších spouštěných pomlčkou nebo interpretovat jiné znaky escape v názvech souborů.
Zobrazí také soubor s názvem cc
dvakrát.
-
Pokud soubor může začínat pomlčkou (např. -n), použijte:
$ ls -d -- ?n -n
Nebo lépe:
$ ls -d ./?n ./-n
Upozornění
-
Glob neodpovídá žádný soubor.
-
Pokud soubory neexistují, globus nebude rozbalen a glob bude vytištěn v původní podobě.
$ echo ?m m? ?m m?
-
Kromě zsh.
$ zsh -c 'echo ?m m?' zsh:1: no matches found: ./m?
Shell se ukončí s chybou.
Toto chování je řízenonomatch
Zsh možnost.$ zsh -c 'setopt +o nomatch; echo ?m m?' ?m m?
Nebo:
$ zsh -c 'echo ?m(N) m?(N)' ?m m?
Ale to vypíše
mm
dvakrát. -
V bash můžete získat podobný výsledek jako zsh, pokud použijete volbu shellu
failglob
je nastaveno:$ bash -c 'shopt -s failglob; echo ?m m?' bash: no match: ?m
Ale skript se nezastaví, shell se neukončí. Technicky vzato, řádek, kde se používá glob, se dále nespouští, ale provádění pokračuje na dalším řádku skriptu.
-
V bash můžete nastavit volbu
nullglob
pro odstranění globů, které se neshodují:$ bash -c 'shopt -s nullglob; echo ?m m? done' done
-
-
Použití ls (podobně jako u jiných programů)
-
S odpovídajícími soubory nebude žádný problém, ale bude také odpovídat (a vypíše) adresáře:
$ ls ?c c? bc cz sc ac: hjk
Raději použijte
-d
sls
(adresáře budou zahrnuty, ale nebudou rozšířeny).$ ls -d ?c c? ac bc cz sc
-
Globy neodpovídají souboru (nebo adresáři)
Poté
ls
ohlásí poruchu$ ls ?m m? ls: cannot access '?m': No such file or directory
Jiné programy možná (pravděpodobně) ne proveďte podobné kontroly.
-
Pomocí
nullglob
s bash dá prázdný seznam ls, takže vypíše obsah nebo pwd, jako by jenls
byl proveden:$ ls ?m m? ac a.out cz 3 b sc ab bc
Tomu by se dalo předejít pomocí
./
$ ls -d ./?m ./m? ls: cannot access './?m': No such file or directory ls: cannot access './m?': No such file or directory
-
Nebo můžete použít regex find (ale bude procházet podadresáře s prune
chybí) (Upozorňujeme, že toto nebude opakovat soubor s názvem cc):
$ find . ! -name . -prune -regex '.*/\(.c\|c.\)'
./ac
./cc
./sc
./bc
./cz