Bash Shell脚本列出给定目录中的文件,以及这些文件是文件还是目录

Bash Shell脚本列出给定目录中的文件,以及这些文件是文件还是目录,bash,shell,Bash,Shell,目前正在学习一些bash脚本,并遇到一个问题,该问题涉及列出给定目录中的所有文件,并说明它们是文件还是目录。我遇到的问题是,我只能得到我的当前目录,或者如果指定了一个目录,它只会说它是一个目录,例如/home/user/shell\u脚本将返回shell\u scipts是一个目录,而不是其中包含的文件。 这就是我到目前为止所做的: dir=$dir for file in $dir; do if [[ -d $file ]]; then echo "$file is a

目前正在学习一些bash脚本,并遇到一个问题,该问题涉及列出给定目录中的所有文件,并说明它们是文件还是目录。我遇到的问题是,我只能得到我的当前目录,或者如果指定了一个目录,它只会说它是一个目录,例如/home/user/shell\u脚本将返回shell\u scipts是一个目录,而不是其中包含的文件。 这就是我到目前为止所做的:

dir=$dir
for file in $dir; do
    if [[ -d $file ]]; then
        echo "$file is a directory"
    if [[ -f $file ]]; then
        echo "$file is a regular file"
    fi
done
或者更换

$(ls $dir)

您的线路:

for file in $dir; do
将仅扩展到单个目录字符串。您需要做的是将其扩展到目录中的文件列表。您可以使用以下方法执行此操作:

for file in "${dir}/"* ; do
这将把
“${dir}/”*
部分扩展到当前目录的仅限姓名的列表中。正如Biffen指出的那样,这应该保证文件列表不会在
文件
中以分割的部分文件名结束,如果其中任何文件名包含空格

如果希望递归到
dir
中的目录中,那么使用
find
可能是更好的方法。只需使用:

for file in $( find ${dir} ); do
请注意,虽然很简单,但这不会处理包含空格的文件或目录。因此,我很想放弃循环,一次性生成输出。这可能与您想要的略有不同,但可能更易于阅读,而且效率更高,尤其是对于大量文件。例如,要列出所有目录,请执行以下操作:

find ${dir} -maxdepth 1 -type d
并列出文件:

find ${dir} -maxdepth 1 -type f
如果要迭代到下面的目录中,请删除
-maxdepth 1

ls -F ~ | \
sed 's#.*/$#/& is a Directory#;t quit;s#.*#/& is a File#;:quit;s/[*/=>@|] / /'
如果文件是目录,则
-F
“分类”开关会附加一个“
/
”。
sed
代码打印所需的消息,然后删除后缀。

这是一个很好的用法:

即使
$dir
中的文件名称中有特殊字符,如空格、星号甚至换行符,这也可以使用


还要注意,变量应该被引用(
“$file”
)。但是
*
不能被引用。我删除了
dir=$dir
,因为它不做任何事情(当
$dir
包含特殊字符时,除了break)。使用:

for file in "${dir}/"* "${dir}/"/.[!.]* "${dir}/"/..?* ; do

如果文件太多(命令行太长),这可能会中断。是的,这是可能的,尽管我已多次使用这种方法处理大量文件(>10^5),并且没有出现问题。我很想放弃
for
/
do
/
done
方法,直接使用
ls
find
命令,如果可能的话,这将更加有效-尽管我试图将其保持在OPs问题的范围内。我会相应地更新。这对包含空格或其他特殊字符的文件名不起作用。当然,我同意
for
示例不起作用。我把第一个换成了更好的。不过,直接的
find
示例应该可以正常工作。当然,这完全取决于输出的用途。一般来说,我发现有101个地方的文件名中包含空格或其他特殊字符会导致问题,因此,如果可能,我会坚持更改它们。这对包含空格或其他特殊字符的文件名不起作用。那么
ls$
应该做什么?!这不适用于名称中有换行符的文件。谢谢@Biffen,这太可怕了,有换行符的文件名是一种东西吗?现在只是查了一下。刚做了一个。刚刚测试了上面的sed代码——失败了。好吧,但谁还想要新词呢,这件事有什么历史?我知道“怎么做”,并寻找“为什么”……我不能真正回答“为什么”,除非回答“为什么不?”可能重复的、等。
ls -F ~ | \
sed 's#.*/$#/& is a Directory#;t quit;s#.*#/& is a File#;:quit;s/[*/=>@|] / /'
for file in "$dir/"*
do
  [[ -d "$file" ]] && echo "$file is a directory"
  [[ -f "$file" ]] && echo "$file is a regular file"
done
for file in "${dir}/"* "${dir}/"/.[!.]* "${dir}/"/..?* ; do