Bash循环遍历包含隐藏文件的目录

西格蒙:

我正在寻找一种方法来对目录中包含的所有内容(包括文件,目录和链接,包括隐藏目录)进行简单的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

我最接近的尝试是使用lsand 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
凯文·蔡斯(Kevin J.Chase):

正如chepner在下面的评论中指出的那样,该解决方案假定您正在将GNU bash和GNU findGNU 一起运行sort

find使用该-maxdepth选项可以防止GNU 递归到子目录中然后使用-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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章