ls $ FOLDER_PATH,空格为$ FOLDER_PATH:没有这样的文件或目录

时间:2015-10-18 12:52:43

标签: bash shell sh

我正在尝试将文件名放在一个只包含一个文件的文件夹中。

仅供参考:$FOLDER_TMP包含空格,这就是我使用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它给了我正确的文件夹。

2 个答案:

答案 0 :(得分:2)

要将输出ls "$FOLDER"存储在变量中,请将其放在子shell中:

FILENAME=$(ls "$FOLDER")

另一个问题是printf。 它在字符串中添加了转义的反斜杠, 当您尝试在下一步中列出目录时, 这些反斜杠在字面上由shell使用。 请放弃printf

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

最后,使用$(...)比使用`...`更好:

答案 1 :(得分:2)

  

我正在尝试将文件名放在一个只包含一个文件的文件夹中。

你肯定有错误的方法。

相反,请考虑像这样使用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 "$1" ]; then
        echo "Oh no, there are no files in your folder"
        return 1
    fi
    # Here, all is good!
    echo "Your file is: $1, I'll store it in variable fname for you"
    fname=$1
}

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

fname=${fname##*/}

更确切地说:在Bash版本中,您可以使用:

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

在POSIX版本中您使用:

fname=${1##*/}

1 使用参数扩展来获取基本名称时有一个问题,它是/的情况。但似乎你不会遇到这种情况,所以这一切都很安全!