将数组用于 ls --ignore

Using array for `ls --ignore`

我正在为我的服务器备份编写 bash 脚本。 基于我的 web root(/home),我想过滤我的 web 目录排除一些将军。 我找到了 --ignore 选项。这是我返回我想要的代码。

DIR_LIST=`ls -al $WWW_ROOT --ignore={.,..,ubuntu,test} | grep "^d" | awk '{ print  }'`
echo $DIR_LIST;

但是当我尝试使用数组时,效果并不好。

EXCLUDED=(. .. test ubuntu)
STR=$(IFS=,; echo "${EXCLUDED[*]}")
DIR_LIST=`ls -al $WWW_ROOT --ignore={$STR} | grep "^d" | awk '{ print  }'`
echo $DIR_LIST;

echo $STR 效果很好,但 echo $DIR_LIST 不是。 我认为支架不能正常工作。

我怎样才能按预期执行此操作?

你的想法大部分是对的,但也有一些问题。首先,ls 命令使用 shell 通配样式来扩展您的 --ignore 模式。当您明确指定它时,它工作正常。

但是当你在变量中定义它来扩展 glob 时,shell 不喜欢它。因为当 shell 展开命令行时,它会先进行 glob 展开,然后再展开变量。由于您在变量中有 glob,当它扩展变量时,它已经越过可以扩展 glob 的点,因此您的 --ignore 模式永远不会按照您期望的方式真正形成。

此外,您填充数组的方式不建议采用这种方法,因为在处理涉及 spaces/newline 或任何名称的名称时,它很脆弱( Why you shouldn't parse the output of ls(1) )其他 shell 个元字符。

请参阅 How to exclude a directory in find . command 以在搜索文件系统时排除目录。

这是一种不使用 ls 的方法,更糟糕的是,您使用的是 -al 标志。

#!/usr/bin/env bash

shopt -s nullglob extglob

files=(/path/to/www/directory/!(ubuntu|test)/)

declare -p files

这将显示数组分配中的文件。

如果您想遍历文件并从文件名中删除路径名而不使用来自 shell 的任何外部命令。

for f in "${files[@]}"; do echo "${f##*/}"; done 

使用basename

时结果相同
for f in "${files[@]}"; do var=$(basename "$f"); echo "$var"; done 

或者直接在数组中做

printf '%s\n' "${files[@]##*/}"

"${files##*/}" 是 P.E 的一种形式。参数扩展。

有在线 bash 手册,您可以在其中查找 P.E。见 Parameter Expansion

或手册页。见 PAGER='less +/^[[:space:]]*parameter\ expansion' man bash

查找 nullglobextglob 参见 shell globbing

名为 files 的数组现在有您感兴趣的 data/files。

默认情况下不列出点文件,因此您不必担心,除非启用 dotglob(默认情况下处于关闭状态)。

如果 "ubuntu" 和 "test" 是文件,它应该可以工作。如果它们是目录,则需要添加点“。” ,例如 EXCLUDED

中的“.test”或“.ubuntu”