mv 和 cp 目录层次结构?

Tim*_*Tim 4 directory file-copy

当我mv或文件时,我也可以移动或复制文件的目录层次结构cp吗?

例如,如果 Imvcp dir1/dir2/file其他地方,它只会mvcp file。如果我也想mv或者cp dir1/dir2怎么办?而不是mkdir -p dir1/dir2,可以用一个命令来完成吗?

Joh*_*ith 9

您可以使用cp--parents开关:

$ mkdir -p step1/step2/step3
$ touch step1/step2/step3/file
$ mkdir copy

$ cp --parents step1/step2/step3/file copy
$ ls copy/step1/step2/step3/file
copy/step1/step2/step3/file
Run Code Online (Sandbox Code Playgroud)

mv,但是,没有--parents开关,但您可以执行以下操作:

$ find step1/step2/step3 -name "file" -exec cp --parents {} copy/ \; -delete
Run Code Online (Sandbox Code Playgroud)

这将:

  • 找到文件。
  • 将它(连同它的父母)复制到目的地。
  • 删除原来的。

您可以为此创建一个函数:

mvparents()
{
    [[ $# -ne 2 ]] && echo "2 arguments needed." && return
    [[ ! -r "$1" ]] && echo "$1 is not readable." && return
    [[ ! -d "$2" ]] && mkdir -p "$2"

    find $(dirname $1) -name "$(basename $1)" -exec cp --parents {} $2/ \; -delete
}

$ mvparents step1/step2/step3/file copy/
Run Code Online (Sandbox Code Playgroud)

如果您尝试移动多个文件,这可能需要进行一些调整。这是一个示例(在 bash 中工作,但不能保证其他 shell):

mvparents()
{
    [[ $# -lt 2 ]] && echo "Usage: $0 [source] <source> ... [destination]." && return

    # Get the destination directory.
    for dest; do true; done
    [[ ! -d "$dest" ]] && mkdir -p "$dest"

    # Copy the arguments and remove the destination.
    parameters=( "$@" )
    unset parameters[${#parameters[@]}-1]

    # For each source file: find, copy, delete.
    for source in "${parameters[@]}"; do
        if [ -r "$source" ]; then
            find $(dirname $source) -name "$(basename $source)" -exec cp --parents {} $dest/ \; -delete
        else
            echo "$0: $source is not readable."
        fi
    done
}
Run Code Online (Sandbox Code Playgroud)

嗯......这比我预期的要长一点,但它应该可以完成这项工作

编辑:正如Sebastian Piech在评论中指出的那样,依赖cpto domv的工作是一个性能杀手,因为mv最初不需要复制文件,只需编辑其元数据。您可能希望将上述循环替换为:

for source in "${parameters[@]}"; do
    if [ -r "$source" ]; then
        [[ ! -d "$dest/$(dirname $source)" ]] && mkdir -p "$dest/$(dirname $source)"
        find $(dirname $source) -name "$(basename $source)" -exec mv {} "$dest/$(dirname $source)" \; -delete
    else
        echo "$0: $source is not readable."
    fi
done
Run Code Online (Sandbox Code Playgroud)

然而,由于这件事情依赖于一个很大的价值$PWD,我想请你必须非常小心,你应该使用它。