我正在寻找一种方法,在bash中对我的目录所包含的内容进行简单的循环,即文件,目录和链接,包括隐藏的内容。
我更愿意,如果它可以专门用于bash,但它必须是最一般的。当然,文件名(和目录名)可以有空格,断行,符号。除了“/”和ASCII NULL(0×0)之外的所有内容,即使在第一个字符处也是如此。此外,结果应排除'。'和'..'目录。
这是循环必须处理的文件生成器:
#!/bin/bash
mkdir -p test
cd test
touch A 1 ! "hello world" \$\"sym.dat .hidden " start with space" $'\n start with a newline'
mkdir -p ". hidden with space" $'My Personal\nDirectory'
所以我的循环看起来应该是(但必须处理上面棘手的事情):
for i in * ;
echo ">$i<"
done
我最接近的尝试是ls
和bash数组的使用,但它无法使用,是:
IFS=$(echo -en "\n\b")
l=( $(ls -A .) )
for i in ${l[@]} ; do
echo ">$i<"
done
unset IFS
或者使用bash数组,但不排除“..”目录:
IFS=$(echo -en "\n\b")
l=( [[:print:]]* .[[:print:]]* )
for i in ${l[@]} ; do
echo ">$i<"
done
unset IFS
答案 0 :(得分:12)
*
与.
开头的文件不匹配,因此您只需要明确:
for i in * .[^.]*; do
echo ">$i<"
done
.[^.]*
将匹配以.
开头的所有文件和目录,后跟非.
字符,后跟零个或多个字符。换句话说,它就像更简单的.*
,但不包括.
和..
。如果您需要匹配..foo
之类的内容,则可以将..?*
添加到模式列表中。
答案 1 :(得分:1)
正如chepner在下面的评论中指出的那样,此解决方案假设您正在运行GNU bash
以及GNU find
GNU sort
......
可以阻止GNU find
使用-maxdepth
选项递归到子目录中。然后使用-print0
以0x00
字节结束每个文件名,而不是通常从-print
获取的换行符。
sort -z
对0x00
字节之间的文件名进行排序。
然后,您可以使用sed
删除点和点点目录条目(尽管GNU find
似乎已经排除了..
。
我还使用sed
来读取每个文件名前面的./
。 basename
也可以这样做,但旧版系统没有basename
,您可能不相信它可以正确处理时髦角色。
(这些sed
命令每个都需要两种情况:一种用于字符串开头的模式,另一种用于0x00
字节之间的模式。这些是如此难看我将它们拆分成单独的功能。)
read
命令没有-z
或-0
选项,就像某些命令一样,但您可以使用-d ""
伪造它并清空IFS
环境变量。
附加-r
选项可防止反斜杠换行组合被解释为行继续。 (另一个名为backslash\\nnewline
的文件会被修改为backslashnewline
。)如果其他反斜杠组合被解释为转义序列,则可能值得一看。
remove_dot_and_dotdot_dirs()
{
sed \
-e 's/^[.]\{1,2\}\x00//' \
-e 's/\x00[.]\{1,2\}\x00/\x00/g'
}
remove_leading_dotslash()
{
sed \
-e 's/^[.]\///' \
-e 's/\x00[.]\//\x00/g'
}
IFS=""
find . -maxdepth 1 -print0 |
sort -z |
remove_dot_and_dotdot_dirs |
remove_leading_dotslash |
while read -r -d "" filename
do
echo "Doing something with file '${filename}'..."
done
答案 2 :(得分:0)
尝试使用find命令,例如:
find .
这将列出所有递归目录中的所有文件。
仅输出不包括前导的文件。或者..尝试:
find . -type f -printf %P\\n
答案 3 :(得分:0)
这可能不是最有利的方式,但我尝试了下面的事情
while read line ; do echo $line; done <<< $(ls -a | grep -v -w ".")
检查我做的下面的踪迹