ls $FOLDER_PATH with space in $FOLDER_PATH: 没有那个文件或目录

ls $FOLDER_PATH with space in $FOLDER_PATH: No such file or directory

我正在尝试获取一个文件夹中只有一个文件的文件名。

仅供参考:$FOLDER_TMP 中包含一个 space,这就是我使用 printf

的原因
function nameofkeyfile(){
    FOLDER_TMP="${PWD%/*/*}/folder/"
    FOLDER=$(printf %q "${FOLDER_TMP}")
    FILENAME=ls "$FOLDER" # Error: No such file or directory
    # or this: FILENAME=$(ls "$FOLDER") # Error: No such file or directory
    FNAME=`basename $FILENAME`
}

问题在于: FILENAME=ls "$FOLDER" # 错误:没有那个文件或目录

你知道为什么吗 - 是的,文件夹就在那里? 如果我回显 $FOLDER 它会给我正确的文件夹。

要将输出ls "$FOLDER"存储在一个变量中,把它放在一个子shell:

FILENAME=$(ls "$FOLDER")

另一个问题是printf。 它在字符串中添加转义反斜杠, 当您尝试在下一步中列出目录时, shell 按字面意思使用了这些反斜杠。 所以删除 printf:

function nameofkeyfile() {
    FOLDER="${PWD%/*/*}/folder/"
    FILENAME=$(ls "$FOLDER")
    FNAME=$(basename $FILENAME)
}

最后,$(...)`...`好用:

I am trying to get the filename in a folder with only one file in it.

你肯定是用错了方法。

相反,请考虑像这样使用 globbing:

作业

fname=( "${PWD%/*/*}"/folder/* )

将填充 数组 fname 将扩展给定的 glob:即目录 "${PWD%/*/*}"/folder/ 中的所有文件,如果有的话。如果根本没有文件,您的数组将逐字包含 glob。

因此,更可靠的方法如下:

nameofkeyfile() {
    fname=( "${PWD%/*/*}"/folder/* )
    # Now check that there's at most one element in the array
    if (( ${#fname[@]} > 1 )); then
        echo "Oh no, there are too many files in your folder"
        return 1
    fi
    # Now check that there is a file
    if [[ ! -f ${fname[0]} ]]; then
        echo "Oh no, there are no files in your folder"
        return 1
    fi
    # Here, all is good!
    echo "Your file is: $fname"
}

这使用 Bash(命名)数组。如果您希望该函数符合 POSIX 标准,这很简单,因为 POSIX shell 有一个未命名的数组(位置参数):

# POSIX-compliant version
nameofkeyfile() {
    set -- "${PWD%/*/*}"/folder/*
    # Now check that there's at most one element in the array
    if [ "$#" -gt 1 ]; then
        echo "Oh no, there are too many files in your folder"
        return 1
    fi
    # Now check that there is a file
    if [ ! -f "" ]; then
        echo "Oh no, there are no files in your folder"
        return 1
    fi
    # Here, all is good!
    echo "Your file is: , I'll store it in variable fname for you"
    fname=
}

我没有从文件名中删除完整路径,但这真的很简单(不要为此使用 basename!):1

fname=${fname##*/}

更准确地说:在 Bash 版本中,您将使用:

fname=${fname[0]##*/}

在 POSIX 版本中,您将使用:

fname=${1##*/}

1在使用参数扩展获取基本名称时有一个问题,就是 / 的情况。不过看来你不会是这种情况,所以一切安好!