【问题标题】:mv a file that contains spaces from a shell scriptmv 包含来自 shell 脚本的空格的文件
【发布时间】:2013-03-25 21:19:52
【问题描述】:

我正在尝试mv 一个文件(重命名它以用破折号替换空格)。如果我传递不带引号的源和目标参数,则源被分解,因为mv 认为它是参数的结尾。

如果我用参数包围 source 和 dest,mv 会报告找不到源。目前,$1 和 $2 在开头和结尾都有硬编码引号。 $onam 和 $dnam 是没有硬编码引号的等价物。

这个来自提示符的命令完美运行,因为 source 和 dest 被引号括起来:

mv "/home/bryan/renametest/TestFolder/test file" "/home/bryan/renametest/TestFolder/test---file"

这是我迄今为止尝试过的(输入和结果)

mv $1 $2
mv: cannot stat `"/home/bryan/renametest/TestFolder/test   file"'
   No such file or directory

mv $onam $dnam
mv: cannot move `/home/bryan/renametest/TestFolder' to a subdirectory of itself, 
  `/home/bryan/renametest/TestFolder/test---file'

mv $1 $dnam
mv: cannot stat `"/home/bryan/renametest/TestFolder/test   file"': 
  No such file or directory

mv $onam $2
mv: cannot move `/home/bryan/renametest/TestFolder' to `"/home/bryan/renametest/TestFolder/test---file"': 
  No such file or directory

如何移动带有空格的文件?

【问题讨论】:

  • 正如对您的其他相关问题之一的评论中所建议的那样,从变量内容中获取引号。否则,shell 将查找名称中带有 " 的文件。
  • 我有带引号和不带引号的。请阅读上文。 “目前,$1 和 $2 在开头和结尾都有硬编码引号。$onam 和 $dnam 是没有硬编码引号的等价物。”

标签: linux shell mv


【解决方案1】:

用途:

mv "$onam" "$dnam"

基本上,在包含可能包含空格的文件名的变量周围使用引号。但是,值本身不应包含引号,除非文件名或目录名称本身包含引号。

不幸的是,我无法立即想到一种简单的方法来使用像$1 这样的值,并在它们周围硬编码引号。您必须与eval 或其他地方混在一起。


SSCCE (Short, Self-Contained, Correct Example)

此代码与您显示的代码同构,但实际上做得更多。它也可以安全运行并在其身后清理。它假设您使用的是bash。请注意,带空格的名称在一行中包含多个空格;如果您尝试使用包含单个空格的名称,很容易被愚弄成一种虚假的安全感。

#!/bin/bash
testdir=test.$$
mkdir "$testdir" || exit 1

trap "rm -fr '$testdir'; exit 1" 0 1 2 3 13 15

(
    set -x
    x=$'\n\n'
    cd test.$$

    basedir="$PWD"
    sub1dir="rename  test"
    sub2dir="Test   Folder"
    subdir="$sub1dir/$sub2dir"

    mkdir -p "$basedir/$subdir"

    oldfile="test   file"

    cp /etc/group "$basedir/$subdir/$oldfile"

    echo "$x"
    ls -lR .

    echo "$x"
    newfile=$(echo "$oldfile" | sed 's/ /-/g')
    mv "$basedir/$subdir/$oldfile" "$basedir/$subdir/$newfile"
    ls -lR .

    echo "$x"
    new2dir=$(echo "$sub2dir" | sed 's/ /-/g')
    mv "$basedir/$subdir"  "$basedir/$sub1dir/$new2dir"
    ls -lR .

    echo "$x"
    new1dir=$(echo "$sub1dir" | sed 's/ /-/g')
    mv "$basedir/$sub1dir" "$basedir/$new1dir"
    ls -lR .
)

rm -fr "$testdir"
trap 0

#    $ mv "/home/bryan/renametest/TestFolder/test   file" "/home/bryan/renametest/TestFolder/test---file"
#
#Here are some inputs and results.
#
#    mv $1 $2
#    mv: cannot stat `"/home/bryan/renametest/TestFolder/test   file"': No such file or directory
#
#    mv $onam $dnam
#    mv: cannot move `/home/bryan/renametest/TestFolder' to a subdirectory of itself, `/home/bryan/renametest/TestFolder/test---file'
#
#    mv $1 $dnam
#    mv: cannot stat `"/home/bryan/renametest/TestFolder/test   file"': No such file or directory
#
#    mv $onam $2
#    mv: cannot move `/home/bryan/renametest/TestFolder' to `"/home/bryan/renametest/TestFolder/test---file"': No such file or directory
#
#Ideas?

你必须小心;请注意我是如何从片段中建立名称并分解它们等的。但是小心,它可以完成。

示例输出

使用bash -x 运行,但您可以只使用bash 运行它,并且您只会跳过一小部分输出,因为它在子shell 代码中包含set -x

+ testdir=test.47648
+ mkdir test.47648
+ trap 'rm -fr '\''test.47648'\''; exit 1' 0 1 2 3 13 15
+ set -x
+ x='

'
+ cd test.47648
+ basedir=/Users/jleffler/tmp/soq/x3/test.47648
+ sub1dir='rename  test'
+ sub2dir='Test   Folder'
+ subdir='rename  test/Test   Folder'
+ mkdir -p '/Users/jleffler/tmp/soq/x3/test.47648/rename  test/Test   Folder'
+ oldfile='test   file'
+ cp /etc/group '/Users/jleffler/tmp/soq/x3/test.47648/rename  test/Test   Folder/test   file'
+ echo '

'



+ ls -lR .
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 rename  test

./rename  test:
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 Test   Folder

./rename  test/Test   Folder:
total 8
-rw-r--r--  1 jleffler  staff  2151 Apr  3 18:43 test   file
+ echo '

'



++ echo 'test   file'
++ sed 's/ /-/g'
+ newfile=test---file
+ mv '/Users/jleffler/tmp/soq/x3/test.47648/rename  test/Test   Folder/test   file' '/Users/jleffler/tmp/soq/x3/test.47648/rename  test/Test   Folder/test---file'
+ ls -lR .
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 rename  test

./rename  test:
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 Test   Folder

./rename  test/Test   Folder:
total 8
-rw-r--r--  1 jleffler  staff  2151 Apr  3 18:43 test---file
+ echo '

'



++ echo 'Test   Folder'
++ sed 's/ /-/g'
+ new2dir=Test---Folder
+ mv '/Users/jleffler/tmp/soq/x3/test.47648/rename  test/Test   Folder' '/Users/jleffler/tmp/soq/x3/test.47648/rename  test/Test---Folder'
+ ls -lR .
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 rename  test

./rename  test:
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 Test---Folder

./rename  test/Test---Folder:
total 8
-rw-r--r--  1 jleffler  staff  2151 Apr  3 18:43 test---file
+ echo '

'



++ echo 'rename  test'
++ sed 's/ /-/g'
+ new1dir=rename--test
+ mv '/Users/jleffler/tmp/soq/x3/test.47648/rename  test' /Users/jleffler/tmp/soq/x3/test.47648/rename--test
+ ls -lR .
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 rename--test

./rename--test:
total 0
drwxr-xr-x  3 jleffler  staff  102 Apr  3 18:43 Test---Folder

./rename--test/Test---Folder:
total 8
-rw-r--r--  1 jleffler  staff  2151 Apr  3 18:43 test---file
+ rm -fr test.47648
+ trap 0

【讨论】:

  • mv "$onam" "$dnam" mv: 无法移动 /home/bryan/renametest/TestFolder' to a subdirectory of itself, /home/bryan/renametest/TestFolder/test---file'
  • $onam=/home/bryan/renametest/TestFolder/测试文件
  • 这是一个单独的问题。您显然正在尝试将文件夹移动到新位置,而该新位置是其当前位置的子目录。您显示的错误信息与$onam 声称的值不一致。在更新您的问题时显示sh -x yourscript 的输出以及您提供的任何团(以便您可以正确格式化输出)。
  • 没有。如果您检查 onam 的值,您将看到 mv 命令破坏了该值,因为“test”和“file”之间有空格。我已经在上面给出了 onam 的确切值。 1 等价于 onam,但带有硬编码的引号。
  • @evilotto:是的,但是旧习惯很难改掉,25 年甚至更多的旧习惯需要大量的杀戮。
猜你喜欢
  • 2013-03-08
  • 2012-10-21
  • 2014-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多