问题描述
我有一个数组,其中包含不同级别目录中的文件路径列表。我只想将该数组过滤为仅文件,这意味着以/
结尾的文件应保留在数组中。在我的文件系统上,所有路径都不是真实路径。我可以使用OS工具检查目录/文件的类型。
file-a
dir/
dir/file-b
dir/dir-2/
dir/dir-2/file-c
并希望将其过滤为以下字符串(无目录):
file-a
dir/file-b
dir/dir-2/file-c
我尝试了以下方法,但是删除了所有包含/
的路径,导致file-a
是唯一的剩余路径。
FILES_ARRAY=( ${FILES_ARRAY[@]//*\/} )
我试图添加一个$
(在正则表达式语法中很常见)来表示结尾,该结尾不会从数组中删除任何内容。
FILES_ARRAY=( ${FILES_ARRAY[@]//*\$/} )
解决方法
两种不同的解决方案,具体取决于filter
的含义:
1-从数组中删除目录条目:
declare -a FILES_ARRAY=([0]="file-a" [1]="dir/" [2]="dir/file-b" [3]="dir/dir-2/" [4]="dir/dir-2/file-c")
echo "++++++++++++++ array - before"
printf "%s\n" ${FILES_ARRAY[@]}
for i in ${!FILES_ARRAY[@]}
do
[[ "${FILES_ARRAY[${i}]}" == */ ]] && unset FILES_ARRAY[${i}] # remove director from array
done
echo "++++++++++++++ array - after"
printf "%s\n" ${FILES_ARRAY[@]}
这将生成:
++++++++++++++ array - before
file-a
dir/
dir/file-b
dir/dir-2/
dir/dir-2/file-c
++++++++++++++ array - after
file-a
dir/file-b
dir/dir-2/file-c
2-将目录条目保留在数组中,但不显示它们;我们可以通过更改for
循环的主体来重新使用以上代码:
declare -a FILES_ARRAY=([0]="file-a" [1]="dir/" [2]="dir/file-b" [3]="dir/dir-2/" [4]="dir/dir-2/file-c")
echo "++++++++++++++ array"
printf "%s\n" ${FILES_ARRAY[@]}
echo "++++++++++++++ display"
for i in ${!FILES_ARRAY[@]}
do
[[ "${FILES_ARRAY[${i}]}" != */ ]] && echo "${FILES_ARRAY[${i}]}" # only display non-directory entries
done
这还会生成:
++++++++++++++ array
file-a
dir/
dir/file-b
dir/dir-2/
dir/dir-2/file-c
++++++++++++++ display
file-a
dir/file-b
dir/dir-2/file-c
,
您可以使用
FILES_ARRAY=(file-a dir/ dir/file-b dir/dir-2/ dir/dir-2/file-c)
NEW_FILES_ARRAY=()
for (( i=0; i<${#FILES_ARRAY[@]}; i++ )); do
if ! [[ "${FILES_ARRAY[$i]}" == */ ]]; then
NEW_FILES_ARRAY+=("${FILES_ARRAY[$i]}");
fi
done
FILES_ARRAY=("${NEW_FILES_ARRAY[@]}")
printf '%s\n' ${FILES_ARRAY[@]}
输出:
file-a
dir/file-b
dir/dir-2/file-c
注释:
-
for (( i=0; i<${#FILES_ARRAY[@]}; i++ )); do ... done
遍历FILES_ARRAY
的长度,为i
分配了数组元素的索引 -
if ! [[ "${FILES_ARRAY[$i]}" == */ ]]
检查当前元素是否不以/
结尾(*
匹配任意数量的字符,/
匹配/
, glob 模式始终需要整个字符串匹配,不需要$
)和 -
NEW_FILES_ARRAY+=("${FILES_ARRAY[$i]}");
将当前项目添加到NEW_FILES_ARRAY
数组中。 -
FILES_ARRAY=("${NEW_FILES_ARRAY[@]}")
重新分配了原始变量,使其包含过滤后的元素
此awk
命令可能会有所帮助,但路径中的空格会失败
new_arr=($(awk '{for (i=1; i<=NF; i++) if ($i !~ /\/$/) {print $i}}' <<< "${arr[@]}"))