0

我没想到这会是个问题。因为我认为 coreutils 支持这些东西,然后 cp ls 和 rm 的肮脏组合就足够了。

但是,事实并非如此,如果您现在向我解释为什么我的方法失败了,以及我应该如何以适当的方式做到这一点,我将不胜感激。

代码

function CheckoutFolder {
    local dir=$1


    mkdir "$dir/.CheckoutFolderTmp"
    (
        cd "$dir" \
        && cp -R $(ls -Q -A "$dir" --ignore=".CheckoutFolderTmp") "$dir/.CheckoutFolderTmp" \
        && rm -Rf  $(ls -Q -A "$dir" --ignore=".CheckoutFolderTmp")
    )
    mv "$dir/.CheckoutFolderTmp" "$dir/src"
    mkdir -p "$dir/"{build,log}
}

样本输出

++ CheckoutFolder /home/tobias/Develop/src/thelegacy/RCMeta
++ local dir=/home/tobias/Develop/src/thelegacy/RCMeta
++ mkdir /home/tobias/Develop/src/thelegacy/RCMeta/.CheckoutFolderTmp
++ cd /home/tobias/Develop/src/thelegacy/RCMeta
+++ ls -Q -A /home/tobias/Develop/src/thelegacy/RCMeta --ignore=.CheckoutFolderTmp
++ cp -R '"build"' '"buildmythli.sh"' '"CMakeLists.txt"' '".directory"' '".libbuildmythli.sh"' '"log"' '"RCMeta"' '"RCMetaTest"' '"src"' /home/tobias/Develop/src/thelegacy/RC
cp: cannot stat `"build"': No such file or directory
cp: cannot stat `"buildmythli.sh"': No such file or directory
cp: cannot stat `"CMakeLists.txt"': No such file or directory
cp: cannot stat `".directory"': No such file or directory
cp: cannot stat `".libbuildmythli.sh"': No such file or directory
cp: cannot stat `"log"': No such file or directory
cp: cannot stat `"RCMeta"': No such file or directory
cp: cannot stat `"RCMetaTest"': No such file or directory
cp: cannot stat `"src"': No such file or directory
++ mv /home/tobias/Develop/src/thelegacy/RCMeta/.CheckoutFolderTmp /home/tobias/Develop/src/thelegacy/RCMeta/src
++ mkdir -p /home/tobias/Develop/src/thelegacy/RCMeta/build /home/tobias/Develop/src/thelegacy/RCMeta/log
++ return 0

神话

4

2 回答 2

2

正如 Les 所说,ls -Q在文件名周围加上引号,这些引号在参数中传递给cpand rm。(使用引号来引用和分隔参数是 Bash 命令行的一个方面,当您实际键入命令时;当您将一个命令的输出传递给另一个命令时,它不起作用。)一般来说,解析的输出ls通常不是一个好主意。

这是另一种方法:

function CheckoutFolder() (
    cd "$1"

    mkdir .CheckoutFolderTmp

    find -mindepth 1 -maxdepth 1 -not -name .CheckoutFolderTmp \
         -exec mv {} .CheckoutFolderTmp/{} \;

    mv .CheckoutFolderTmp src

    mkdir build log
)

(请注意,我用括号(...)而不是花括号包围了函数体{...}。这会导致整个函数在子shell中运行。)

于 2012-09-12T17:52:29.440 回答
1

$(ls ...) 命令在名称周围加上不需要的引号。考虑改用 xargs 和反引号。例如...

(cd "$dir" && cp -R `ls -Q -A "$dir" --ignore=".CheckoutFolderTmp"` "$dir/.CheckoutFolderTmp" && ls -Q -A "$dir" --ignore=".CheckoutFolderTmp" | xargs rm -Rf  )

cp 输出不太友好,但它确实提供了您需要的信息。

cp:  cannot stat '"build"': No such file or directory

跳到最后的陈述“没有这样的文件或目录”。“cannot stat” 很神秘,但这意味着“cp”使用“stat”来获取有关它试图复制的文件或目录的一些信息。“统计”失败。它在名为“build”的文件(或目录)上出现“没有这样的文件或目录”的 errno 失败。这是因为,cp 内部的实际参数是“build”(注意)引号),而您想要的文件名是 build(注意没有引号)。

使用 -Q 调用 $(ls... ) 以添加引号(大概是为了处理带有空格和逗号以及其他违规字符的文件名)。但是 $(ls...) 已经为您添加了引号。如果您使用 -0,xargs 也可以处理时髦的文件名。

于 2012-09-12T17:33:23.163 回答