[英]Bash loop through directory including hidden file
I am looking for a way to make a simple loop in bash over everything my directory contains, ie files, directories and links including hidden ones. 我正在寻找一种方法来在我的目录包含的所有内容上进行bash的简单循环,即文件,目录和包含隐藏的链接。
I will prefer if it could be specifically in bash but it has to be the most general. 我更愿意,如果它可以特别在bash中,但它必须是最一般的。 Of course, file names (and directory names) can have white space, break line, symbols. 当然,文件名(和目录名)可以有空格,断行,符号。 Everything but "/" and ASCII NULL (0×0), even at the first character. 除了“/”和ASCII NULL(0×0)之外的所有内容,即使在第一个字符处也是如此。 Also, the result should exclude the '.' 此外,结果应排除'。' and '..' directories. 和'..'目录。
Here is a generator of files on which the loop has to deal with : 这是循环必须处理的文件生成器:
#!/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'
So my loop should look like (but has to deal with the tricky stuff above): 所以我的循环应该看起来像(但必须处理上面的棘手的东西):
for i in * ;
echo ">$i<"
done
My closest try was the use of ls
and bash array, but it is not working with, is: 我最接近的尝试是使用ls
和bash数组,但它无法使用,是:
IFS=$(echo -en "\n\b")
l=( $(ls -A .) )
for i in ${l[@]} ; do
echo ">$i<"
done
unset IFS
Or using bash arrays but the ".." directory is not exclude: 或者使用bash数组,但不排除“..”目录:
IFS=$(echo -en "\n\b")
l=( [[:print:]]* .[[:print:]]* )
for i in ${l[@]} ; do
echo ">$i<"
done
unset IFS
*
doesn't match files beginning with .
*
与以...开头的文件不匹配.
, so you just need to be explicit: ,所以你只需要明确:
for i in * .[^.]*; do
echo ">$i<"
done
.[^.]*
will match all files and directories starting with .
.[^.]*
将匹配以.
开头的所有文件和目录.
, followed by a non- .
,其次是非.
character, followed by zero or more characters. 字符,后跟零个或多个字符。 In other words, it's like the simpler .*
, but excludes .
换句话说,它就像更简单.*
,但不包括在内.
and ..
. 和..
If you need to match something like ..foo
, then you might add ..?*
to the list of patterns. 如果你需要匹配像..foo
这样的..foo
,那么你可以将..?*
添加到模式列表中。
As chepner noted in the comments below, this solution assumes you're running GNU bash
along with GNU find
GNU sort
... 正如chepner在下面的评论中指出的,这个解决方案假设你运行GNU bash
以及GNU find
GNU sort
...
GNU find
can be prevented from recursing into subdirectories with the -maxdepth
option. 可以使用-maxdepth
选项阻止GNU find
重新进入子目录。 Then use -print0
to end every filename with a 0x00
byte instead of the newline you'd usually get from -print
. 然后使用-print0
以0x00
字节结束每个文件名,而不是通常从-print
获取的换行符。
The sort -z
sorts the filenames between the 0x00
bytes. sort -z
对0x00
字节之间的文件名进行sort -z
。
Then, you can use sed
to get rid of the dot and dot-dot directory entries (although GNU find
seems to exclude the ..
already). 然后,你可以使用sed
摆脱点和点点目录条目(尽管GNU find
似乎已经排除了..
)。
I also used sed
to get read of the ./
in front of every filename. 我还使用sed
来读取每个文件名前面的./
。 basename
could do that too, but older systems didn't have basename
, and you might not trust it to handle the funky characters right. basename
也可以这样做,但是旧系统没有basename
,你可能不相信它可以正确处理时髦的角色。
(These sed
commands each required two cases: one for a pattern at the start of the string, and one for the pattern between 0x00
bytes. These were so ugly I split them out into separate functions.) (这些sed
命令每个都需要两种情况:一种用于字符串开头的模式,另一种用于0x00
字节之间的模式。这些很难看,我将它们拆分成单独的函数。)
The read
command doesn't have a -z
or -0
option like some commands, but you can fake it with -d ""
and blanking the IFS
environment variable. read
命令没有像某些命令那样的-z
或-0
选项,但您可以使用-d ""
伪造它并消隐IFS
环境变量。
The additional -r
option prevents a backslash-newline combo from being interpreted as a line continuation. 附加-r
选项可防止反斜杠换行组合被解释为行继续。 (A file called backslash\\\\nnewline
would otherwise be mangled to backslashnewline
.) It might be worth seeing if other backslash-combos get interpreted as escape sequences. (一个名为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
Try the find command, something like: 尝试使用find命令,例如:
find .
That will list all the files in all recursive directories. 这将列出所有递归目录中的所有文件。
To output only files excluding the leading . 仅输出不包括前导的文件。 or .. try: 或..尝试:
find . -type f -printf %P\\n
It may not be the most favorable way but I tried bellow thing 它可能不是最有利的方式,但我尝试了下面的事情
while read line ; do echo $line; done <<< $(ls -a | grep -v -w ".")
check the below trail which I did 检查我做的下面的踪迹
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.