我尝试这样做ls [a-z][a-z]
,但似乎不起作用。
答案1
使用 bash,设置 glob 设置,以便丢失的匹配项不会触发错误:
shopt -u failglob # avoid failure report (and discarding the whole line).
shopt -s nullglob # remove (erase) non-matching globs.
ls ?c c?
问号是代表单个字符的全局字符。由于您需要两个字符的文件名,因此其中一个必须是 a c
,因此它要么是第一个字符,要么是最后一个字符。
这样shopt -s dotglob
还会出现一个名为.c
.
如果没有匹配的文件,设置这些 shell 选项会导致所有参数被删除,从而导致默认ls
列出任何内容/所有内容。
改用这个:
shopt -s nullglob ## drop any missing globs
set -- ?c c? ## populate the $@ array with (any) matches
if [ $# -gt 0 ] ## if there are some, list them
ls -d "$@"
fi
答案2
我认为更好的方法是使用find
:
find . -type f -name '*c*' -name '??'
这将递归搜索。仅列出当前目录中的文件:
find . ! -name . -prune -type f -name '*c*' -name '??'
答案3
如果文件存在(并且没有转义字符,例如\c
),则可以使用 glob:
echo ?c c?
它将匹配包含一个字符 ( ?
) 后跟一个字符的文件c
或包含c
一个字符后跟一个字符 ( ?
) 的文件。
但会因文件而失败名字以破折号(如-n
or 或)开头-e
,并以反斜杠字符(如\c
or \n
with echo
as 两者)开头-e
,并且-n
对于(某些 shell)是特殊的echo
,并且\c
or\n
将被解释为转义序列(\c
结束输出并打印新行,而不是某些 shell 实现中的\n
逐字字符设置\n
选项时使用 echo 和 bash )。shopt -s xpg_echo
其他应用程序或实用程序(例如ls
)将具有一些其他选项,并且可能会因许多其他破折号开头或解释文件名中的其他转义字符而失败。
还将列出一个名为cc
两次的文件。
如果文件可能以破折号开头(如 -n),请使用:
$ ls -d -- ?n -n
或更好:
$ ls -d ./?n ./-n
注意事项
全局匹配没有文件。
如果文件不存在,则不会扩展 glob,并且会以其原始形式打印 glob。
$ echo ?m m? ?m m?
除了 zsh 之外。
$ zsh -c 'echo ?m m?' zsh:1: no matches found: ./m?
shell 将退出并出现错误。
此行为由兹什的nomatch
选项。$ zsh -c 'setopt +o nomatch; echo ?m m?' ?m m?
或者:
$ zsh -c 'echo ?m(N) m?(N)' ?m m?
但这会打印
mm
两次。failglob
在 bash 中,如果设置了shell 选项,您可以获得与 zsh 类似的结果:$ bash -c 'shopt -s failglob; echo ?m m?' bash: no match: ?m
但脚本不会停止,shell也不会退出。好吧,从技术上讲,使用 glob 的行不会进一步执行,而是在下一个脚本行继续执行。
在 bash 中,您可以设置选项
nullglob
来删除不匹配的 glob:$ bash -c 'shopt -s nullglob; echo ?m m? done' done
使用 ls (与其他程序类似)
匹配文件不会有问题,但也会匹配(并列出)目录:
$ ls ?c c? bc cz sc ac: hjk
更好地使用
-d
withls
(目录将被包含但不扩展)。$ ls -d ?c c? ac bc cz sc
Glob 无法匹配文件(或目录)
然后
ls
会报失败$ ls ?m m? ls: cannot access '?m': No such file or directory
其他程序可能(可能)这样做不是做类似的检查。
与 bash 一起使用
nullglob
会给 ls 一个空列表,因此,它将列出内容或 pwd,就好像只ls
执行了一样:$ ls ?m m? ac a.out cz 3 b sc ab bc
这可以避免使用
./
$ ls -d ./?m ./m? ls: cannot access './?m': No such file or directory ls: cannot access './m?': No such file or directory
或者您可以使用查找正则表达式(但它将遍历prune
缺少的子目录)(请注意,这不会重复名为 cc 的文件):
$ find . ! -name . -prune -regex '.*/\(.c\|c.\)'
./ac
./cc
./sc
./bc
./cz
答案4
在bash
:
后跟
c
字符 (?c
) 或字符(包括.
)dotglob
后跟c
(?c
)。shopt -s extglob failglob dotglob printf '%s\n' @(?c|c?)
除不包含
c
(!(*c*)
) 或不是两个字符 (!(??)
) 的文件之外的所有文件。这里使用双重否定来实现合取。shopt -s extglob failglob dotglob printf '%s\n' !(!(*c*)|!(??))
在zsh
:
printf '%s\n' (?c|c?)(D)
(其中
D
启用dotglob
;failglob
(nomatch
在 中调用zsh
)默认情况下处于启用状态)。双重否定使用
~
除了运算符和^
否定扩展运算符:set -o extendedglob printf '%s\n' *c*~^??(D)
在ksh93
:
ksh93 中没有
nomatch
/failglob
选项,但您可以在那里手动完成:FIGNORE='@(.|..)' # only ignore . and .. and not the other dotfiles files=(~(N)@(?c|c?)) if ((${#files[@]})); then printf '%s\n' "${files[@]}" else echo >&2 No match exit 1 fi
(其中
~(N)
启用nullglob
该全局)。ksh93
确实有一个合取运算符。所以在这里,您还可以将该files=(...)
行更改为:files=(~(N)@(*c*&??))