我有一个 bash 脚本,需要循环遍历文件夹中的所有文件。
这是我目前的职能:
function listDir(){
for file in "$1"/*;
do
echo $file
done
}
问题是它没有列出隐藏文件或文件夹(.hiddenFile)。我怎样才能做到这一点?
根据 Kusalananda 的回答,我已将脚本编辑为如下所示:
listDir () {
for file in $(find "$1" -maxdepth 1 -mindepth 1 -print);
do
echo $file
done
}
但是,这不适用于名称中带有空格的文件夹。请注意,我需要 for 循环来使用该文件名执行其他操作,而不仅仅是列出它们。
我该如何解决这个问题?
答案1
默认情况下, shell*
通配模式不匹配隐藏名称。
在 中bash
,您可以通过启用 shell 选项来实现这一点dotglob
。你用 来执行此操作shopt -s dotglob
。
请注意,您还必须$file
在代码中引用 的扩展,否则 shell 将对其值执行分词和文件名通配。
listDir () (
shopt -s dotglob
for pathname in "$1"/*; do
printf '%s\n' "$pathname"
done
)
如果您需要$pathname
在上面的循环中执行其他操作,请确保将变量的扩展双引号为 as "$pathname"
。这将使该函数适用于包含各种字符的文件名。
调用该函数时,如果目录名称包含空格,请确保引用该目录名称:
listDir "my directory/here somewhere"
两种替代方法(假设您只需要列出文件):
listDir () (
shopt -s dotglob
printf '%s\n' "${1:-.}"/*
)
通过将函数体包含在( ... )
(子 shell)中,我们确保dotglob
在调用 shell 中不会设置 shell 选项。
通过使用${1:-.}
in 代替 just ,如果没有给出目录(或空字符串),$1
我们使用(当前目录)作为默认目录来列出。.
printf
如果给出的参数多于格式化字符串中的占位符,则实用程序将重用其格式字符串。在这里,我们使用这一事实将文件名打印为换行符分隔列表。
使用find
,不需要dotglob
:
listDir () {
find "${1:-.}" -maxdepth 1 -mindepth 1 -print
}
如果您想在使用时对找到的文件执行其他操作find
,那么不尝试循环 的输出find
。相反,使用-exec
:
listDir () {
find "${1:-.}" -maxdepth 1 -mindepth 1 -exec sh -c '
for pathname do
# code that does something with "$pathname"
done' sh {} +
}
有关的:
答案2
由于您已经标记了 bash,因此您还可以使用数组:
shopt -s dotglob
files=( "$1"/* )
然后您可以打印它们或对其进行操作:
printf "File: %s\n" "${files[@]}"
或者
rm "${files[@]}"
或者
for f in "${files[@]}"; do mv "${f}" "renamed-${f}"; done