【问题标题】:basename with spaces in a bash script?bash脚本中带有空格的basename?
【发布时间】:2011-08-25 16:48:23
【问题描述】:

我正在编写一个 bash 脚本,以使用文件名在 /tmp/ 中创建一个新文件夹,然后将文件复制到该文件夹​​中。

#!/bin/bash

MYBASENAME="`basename $1`"
mkdir "/tmp/$MYBASENAME"

for ARG in "$@"
    do
        mv "$ARG" "/tmp/$MYBASENAME"

done

行为:

当我输入 mymove "/home/me/downloads/my new file.zip" 时,它会显示:

mkdir /tmp/my
new
file.zip
mv: rename /home/me/downloads/my new file.zip to /tmp/my\nnew\nfile.zip:

我对所有内容都有很多引用,所以我不明白为什么这不能按预期工作。

另外,我有表单循环,以防有多个文件。我希望根据第一个参数的基本名称将它们全部复制到同一个文件夹中。

【问题讨论】:

    标签: linux bash unix shell scripting


    【解决方案1】:

    如果赋值是单个命令替换,则不需要引用命令替换。 shell 不会对变量赋值进行分词。

    MYBASENAME=$(basename "$1")
    

    就是这样。您应该养成使用 $() 而不是反引号的习惯,因为 $() 更容易嵌套(顺便说一句,它是 POSIX,并且所有现代 shell 都支持它。)

    PS:你应该尝试编写bash脚本。尝试编写 shell 脚本。不同之处在于没有 bashisms、zshisms 等。就像 C 语言一样,可移植性是脚本的理想特性,特别是如果它可以轻松实现的话。您的脚本不使用任何 bashism,所以我会写 #!/bin/sh。对于挑剔者:是的,我知道,旧的 SunOS 和 Solaris /bin/sh 不理解 $(),但 /usr/xpg4/bin/sh 是 POSIX shell。

    【讨论】:

    • 我注意到很多默认的 shell 脚本使用 sh 而不是 bash。除了echo \c 之类的东西以防止出现新行之外,我仍然无法区分太多。感谢您的提示和有用的答案。
    • echo \c 的可移植方式是使用printf,您只需在格式字符串中省略\n。最常用的 bashism 可以说是使用数组变量、非 POSIX 语法(如用于测试的 [[ ... ]])、带有 for (( ... )) 的循环以及 select 构造。
    • 这不适用于我的 macosx lion 上附带的 bash(GNU bash,版本 3.2.48(1)-release (x86_64-apple-darwin11)
    • @rjha94 究竟是什么不起作用?结果是什么?请非常具体。
    • @jens 我的错,我忘记了名字周围的“引号”
    【解决方案2】:

    问题是$1

    MYBASENAME="`basename $1`" 
    

    没有被引用。改用这个:

    MYBASENAME="$(basename "$1")"
    

    【讨论】:

    • +1 用于使用 $() 形式的命令替换。伙计们,除非您真的非常确定您将使用一个只有 bourne shell 的系统,否则为什么不将您的技术语法升级到 1993 标准 ;-) !我敢打赌你使用sed -i 而不考虑它。但是你不会在依赖 bourne shell 或 100 个其他 gnu/linux-isms 的系统上找到 sed -i。祝你们好运。
    【解决方案3】:

    您缺少一组引号!

    MYBASENAME="`basename \"$1\"`"
    

    这会解决你的问题。

    【讨论】:

    • 你写的一对引号和反斜杠太多了:-)
    【解决方案4】:
    MYBASENAME="`basename $1`"
    

    应该是

    MYBASENAME="`basename "$1"`"
    

    用双引号 "$1"$1 括起来

    【讨论】:

      【解决方案5】:

      我只是在复制来自[SOLVED] mv: target `filename' is not a directory 的内容;归功于原始响应者:

      将此添加到脚本的开头。它改变了内部字段 分隔符仅换行,您的脚本会将空格视为 从那时起另一个角色。

      #!/bin/bash
      
      IFS='
      '
      
      <your script>
      

      此 Wikipedia 页面详细介绍了特殊的 shell 变量:Internal field separator

      【讨论】:

        猜你喜欢
        • 2014-06-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-01
        • 1970-01-01
        • 2015-10-21
        • 2012-11-15
        • 2010-10-10
        相关资源
        最近更新 更多