无法使用脚本查看父目录中的文件

无法使用脚本查看父目录中的文件

我有一个脚本,它在当前工作目录中查找文件,并判断文件是文件还是目录

for file in $(ls | sort) ; do
        if [ -d $file ]
        then
                echo "$file is a directory"
        fi
        if [ -f $file ]
        then
                echo "$file is a file"
        fi
done

一切正常。但是,当我编辑它以查看父目录中的文件时,我没有得到任何输出。我改变了这个

for file in $(ls | sort) ; do

更改为:

for file in $(ls .. | sort) ; do

我这里遗漏了什么吗?

答案1

建议

在 bash 中列出文件和目录时,使用 Shell 通配符查找文件名是最有效、最可靠的方法……几乎所有其他外部文件列表工具都容易出错,例如单词拆分在处理其输出时在 bash 中并且它们需要在脚本中实现特殊的处理/输出格式和错误处理机制才能可靠地与它们一起工作在 bash 中... 默认情况下,它们的输出可能未被格式化为可在 bash 中可靠处理。

所以, …

要处理当前目录中的文件和目录,请使用:

for f in *; do
  if [ -d "$f" ]; then
    echo "$f is a directory"
  elif [ -f "$f" ]; then
    echo "$f is a file"
    fi
  done

注意双引号(")围绕参数$f 必须在循环体内使用(即两个命令结构之间do … done) 但一定不在循环头部使用(IEfor f in *;)。

要仅对目录进行操作,请使用:

for f in */; do ...

要处理父目录内容,请使用:

for f in ../*; do ...

或者限制仅在父目录中的目录,使用:

for f in ../*/; do ...

请注意,bash 中的 shell 文件名默认按字母和数字顺序排序。

请注意,的输出ls也将默认排序,因此您不需要sort像在示例中那样将其通过管道传输...ls除非您知道后果,否则请不要以这种方式解析输出...请参阅为什么不是解析ls(以及该做什么)?

示范

为了进一步了解差异,请看下面的演示:

创建以下四个文件:

touch 3_with_tab$'\t'file.txt; touch 1_with_newline$'\n'file.txt; touch '2_with_space file.txt'; touch 4_normal_file.txt

使用 shell 通配符列出它们...完美运行

for f in *; do [ -f "$f" ] && echo "$f is a file"; done
1_with_newline
file.txt is a file
2_with_space file.txt is a file
3_with_tab      file.txt is a file
4_normal_file.txt is a file

通过find管道传输到while循环......文件名包含换行符时失败

find | while IFS= read -r f; do [ -f "$f" ] && echo "$f is a file"; done
./3_with_tab    file.txt is a file
./4_normal_file.txt is a file
./2_with_space file.txt is a file

在循环findfor...文件名包含空格、制表符或换行符时失败

for f in $(find); do [ -f "$f" ] && echo "$f is a file"; done
./4_normal_file.txt is a file

通过ls管道传输到while循环......文件名包含换行符时失败

ls | while IFS= read -r f; do [ -f "$f" ] && echo "$f is a file"; done
2_with_space file.txt is a file
3_with_tab      file.txt is a file
4_normal_file.txt is a file

在循环lsfor...文件名包含空格、制表符或换行符时失败

for f in $(ls); do [ -f "$f" ] && echo "$f is a file"; done
4_normal_file.txt is a file

机制(find例如

但是,如果你必须使用外部文件列表工具,那么你需要注意格式化它的输出并将其作为 bash 的输入读取……例如find,你最好的选择是使用find的行动-print0NULL 分隔输出)通过管道传输到一个while循环,利用read使用-dbash的 ANSI-C 引用 $'\0'像这样:

find -print0 | while IFS= read -r -d $'\0' f; do [ -f "$f" ] && echo "$f is a file"; done
./3_with_tab    file.txt is a file
./4_normal_file.txt is a file
./1_with_newline
file.txt is a file
./2_with_space file.txt is a file

或者使用sort的选项-z行分隔符为 NULL,而不是换行符)像这样:

find -print0 | sort -z | while IFS= read -r -d $'\0' f; do [ -f "$f" ] && echo "$f is a file"; done
./1_with_newline
file.txt is a file
./2_with_space file.txt is a file
./3_with_tab    file.txt is a file
./4_normal_file.txt is a file

答案2

是的,你漏掉了一些东西。你列出了父目录中的文件,但是当你检查它是文件还是目录时,你仍然在当前目录中 - 你必须像这样修改它才能使用父目录:

for file in $(ls .. | sort) ; do
        if [ -d "../$file" ]
        then
                echo "$file is a directory"
        fi
        if [ -f "../$file" ]
        then
                echo "$file is a file"
        fi
done

然而,正如评论所表明的,这不一定是解决这个问题的最佳方法。

相关内容