显示目录列表的 Bash 脚本出错

ank*_*981 3 bash shell-script

我写了一个简单的 bash 脚本(我对它很陌生,你知道!)接受一个目录作为它的参数并打印它的列表,测试文件和目录。这是我如何处理它:

#!/bin/bash
# Lists all files and directories (non-recursively) in a specified directory

if [ $# -gt 1 ]; then
    echo "Error. Please specify only one directory. ($#)"
    exit
fi

if [ -z $1 ]; then
    echo "No directory specified. Exiting."
    exit
fi

echo "Listing for $1:"

$dirs=`ls $1`
echo "Dirs: $dirs" # Just to confirm if all is well

# Loop through and print
for i in $dirs;
do
    if [ -f $i ]; then
        echo "File: $i"
    elif [ -d $i ]; then
        echo "Directory: $i"
    fi
done
Run Code Online (Sandbox Code Playgroud)

问题出在我的 for 循环中。当我运行此脚本并将其提供给我的主目录时,出现此错误:

./list_files_and_dirs.sh: line 16: =Calibre: command not found

我知道我在涉及变量的命令替换中犯了一个错误,但我不知道是什么。有人请帮忙!

================ 更新 ================

这是根据答案输入的新(最后一部分)代码:

dirs=`ls "$1"`
#echo "Dirs: $dirs" # Just to confirm if all is well

IFS=$'\n'

# Loop through and print
for i in $dirs;
do
    if [ -f "$i" ]; then
        echo "File: $i"
    elif [ -d "$i" ]; then
        echo "Directory: $i"
    fi
done
Run Code Online (Sandbox Code Playgroud)

mar*_*nus 9

注意:我假设您是在自学 Bash。不要在生产中使用此代码。find "$directory" -maxdepth 1 -type d会给你目录,-type f会给你文件。

既然是在抱怨第16行,我们来看看:

$dirs=`ls $1`
Run Code Online (Sandbox Code Playgroud)

如果要分配给变量,则不应包含$. 我猜你的意思是:

dirs=`ls $1`
Run Code Online (Sandbox Code Playgroud)

现在发生的事情是这样的:

  • $dirs 可能是空的,所以什么都没有代替。
  • ls命令运行,并且在“命令”它的输出取代。
  • 目录中的第一个文件名为Calibre,留下命令:=Calibre x y z ...
  • =Calibre 不是有效的命令,因此错误。

然而,我们还没有到那里:如果任何文件名中有空格,这就会出错。为了解决这个问题,你需要做更多的事情:

  • 您需要IFS=$'\n'for循环之前的某个地方包含。这将字段分隔符设置为换行符,这会阻止for循环拆分空格或制表符上的文件(技术上,文件的文件名中也有换行符:您不太可能遇到这样的文件,在这种情况下,如果您遇到这样的文件,它不会导致严重问题,但值得注意这种可能性,以防万一它真的很重要)。
  • 为了有空格的文件名不转成几个不同的参数-f-d,你需要把报价$i。(所以:[ -f "$i" ][ -d "$i" ]。为了支持其中包含空格的目录,您应该对$1使用它的地方执行相同的操作。


ter*_*don 5

Marinus 已经解释了为什么您会收到该错误。我想指出这里没有必要ls。这样,您就可以避免解析其输出时出现的所有问题。你可以这样做:

#!/bin/bash
# Lists all files and directories (non-recursively) in a specified directory

if [ "$#" -gt 1 ]; then
    echo "Error. Please specify only one directory. ($#)"
    exit
fi

if [ -z "$1" ]; then
    echo "No directory specified. Exiting."
    exit
fi

echo "Listing for $1:"

# Loop through and print
for i in "$1"/*;
do
    if [ -f "$i" ]; then
        echo "File: $i"
    elif [ -d "$i" ]; then
        echo "Directory: $i"
    fi
done
Run Code Online (Sandbox Code Playgroud)