Bash循环目录包括隐藏文件

Sig*_*mun 6 linux 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'
Run Code Online (Sandbox Code Playgroud)

所以我的循环应该看起来像(但必须处理上面棘手的东西):

for i in * ;
  echo ">$i<"
done
Run Code Online (Sandbox Code Playgroud)

我最接近的尝试是使用ls和bash数组,但它无法使用,是:

IFS=$(echo -en "\n\b")
l=( $(ls -A .) )
for i in ${l[@]} ; do
echo ">$i<"
done
unset IFS
Run Code Online (Sandbox Code Playgroud)

或者使用bash数组,但不排除".."目录:

IFS=$(echo -en "\n\b")
l=( [[:print:]]* .[[:print:]]* )
for i in ${l[@]} ; do
echo ">$i<"
done
unset IFS
Run Code Online (Sandbox Code Playgroud)

che*_*ner 12

*与开头的文件不匹配.,因此您只需要明确:

for i in * .[^.]*; do
    echo ">$i<"
done
Run Code Online (Sandbox Code Playgroud)

.[^.]*将匹配所有以..开头的文件和目录,后跟非.字符,后跟零个或多个字符.换句话说,它就像更简单.*,但排除....如果你需要匹配类似的东西..foo,那么你可以添加..?*到模式列表中.


Kev*_*ase 1

正如切普纳在下面的评论中指出的那样,该解决方案假设您正在运行 GNUbash以及 GNU findGNU sort...

find使用该选项可以防止GNU递归到子目录中-maxdepth。然后用-print0一个字节来结束每个文件名,0x00而不是通常从-print.

sort -z对字节之间的文件名进行排序0x00

然后,您可以使用sed来删除点和点-点目录条目(尽管 GNUfind似乎..已经排除了)。

我还习惯于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
Run Code Online (Sandbox Code Playgroud)