上下文:OSX Catalina (zSh) 和 Ubuntu 16.04 (Bash)。 OSX 终端命令:
FILES="$PWD/*" #list of files
echo $FILES
将所有文件的字符串返回到控制台。目前,我打算在要处理的目录中植入脚本的副本。将来,我希望让脚本能够接受要处理的参数(目录)。
假设工作目录中存在文件类型(扩展名而不是隐藏文件):
- .abc
- .ABC
- .def
- .ghi
- .jkl
- .sh
我对上述说明的修改示例感兴趣,这些示例将:
- 仅显式选择 .abc .ABC 和 .def 文件类型(扩展名)
- 选择所有文件除了.sh 和 .jkl
理想情况下会有一个命令选项来指定不区分大小写
答案1
您可以使用 bash 中的数组轻松完成此操作(这是 Ubuntu 上的默认 shell,macOS 的新版本是 bash 或 zsh;这些解决方案与 bash 相关):
选择所有文件(您的原始命令,稍作修改):
$ shopt -s nullglob $ files=(*) $ echo "${files[@]}" file.abc file.ABC file.def file.ghi file.jkl file.sh
nullglob
如果目录为空,则打开该选项会给出一个空列表。如果没有此选项,如果目录为空,files
则将是一个元素的列表,该元素是未展开的*
..abc
仅选择名称以或.ABC
或结尾的文件.def
:$ shopt -s nullglob $ files=(*.abc *.ABC *.def) $ echo "${files[@]}" file.abc file.ABC file.def
选择除名称以
.sh
或结尾的文件之外的所有文件.jkl
$ shopt -s extglob nullglob $ files=(!(*.sh|*.jkl)) $ echo "${files[@]}" file.abc file.ABC file.def file.ghi
不区分大小写的匹配
$ shopt -s nocaseglob nullglob $ files=(*abc) $ echo "${files[@]}" file.abc file.ABC
另外,请注意您正在做什么。files="$PWD/*"
不会将 的值设置$files
为当前目录中的所有文件。它将其值设置为以 结尾的字符串/*
:
$ cd /tmp/current_directory
$ files="$PWD/*"
$ echo "$files"
/tmp/current_directory/*
您认为它有效的原因是因为您使用的是echo $files
未加引号的,这意味着 shell 正在扩展/tmp/current_directory/*
。但是,如果您随后要删除这些文件,则相同的echo
命令将简单地打印/tmp/current_directory/*
并$PWD
扩展到您最初运行该命令的任何目录。文件列表不会与变量一起保存。像我在这里所做的那样使用数组可确保变量存储实际的文件列表,而不仅仅是可以根据使用位置扩展到不同值的 glob。
答案2
在zsh
:
files=($PWD/*.(abc|ABC|DEF)(N))
print -rC1 -- $files # print raw, on one column.
((N)
使用应用于nullglob
该 glob 的限定符,使其$files
成为模式的空列表与任何文件不匹配,而不是报告错误)。
对于.sh
和以外的文件.jkl
:
set -o extendedglob # needed for the ^ negation operator
files=($PWD/^*.(sh|jkl)(N))
对于不区分大小写的匹配(.ABC
/ .abc
/ .Abc
...):
set -o extendedglob
files=($PWD/*.(#i)abc(N))
你的:
FILES="$PWD/*"
echo $FILES
有几个帐户是错误的:
FILES="$PWD/*"
不将文件列表存储在$FILE
变量中。这是一个标量赋值,它只能存储一个值。相反,它存储在后面跟着字面意思$FILES
的内容中。$PWD
/*
在,echo $FILES
如未$FILES
引用的那样,在bash
(但不是zsh
)中, 的扩展$FILES
受到 split+glob 的影响。就在那时,假设$FILES
不包含任何字符$IFS
(这将触发分裂部分),并且$PWD
不包含通配符(这也会触发 glob 部分),该值将扩展到匹配文件列表。
在 中zsh
, split+glob 并不是在参数扩展时隐式完成的,您需要显式地请求它们($=FILES
对于分割,$~FILES
对于通配符,$=~FILES
对于两者)。
然后使用echo
输出任意数据是错误的,echo
默认情况下进行额外处理也是错误的(在 中zsh
,您可以使用echo -E - $files
或print -r -- $files
)。