web-dev-qa-db-ja.com

mvおよびcpディレクトリ階層?

ファイルをmvまたはcpしたときに、ファイルのディレクトリ階層を移動またはコピーすることもできますか?

たとえば、他の場所でmvまたはcpdir1/dir2/fileの場合、mvまたはcpfileのみになります。 mvまたはcpdir1/dir2も必要な場合はどうなりますか? mkdir -p dir1/dir2ではなく、1つのコマンドで実行できますか?

4
Tim

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

ただし、mvには--parentsスイッチはありませんが、次のようなことができます。

$ find step1/step2/step3 -name "file" -exec cp --parents {} copy/ \; -delete

どちらになりますか:

  • ファイルを見つけます。
  • それを(その親と一緒に)宛先にコピーします。
  • オリジナルを削除します。

このための関数を作成できます。

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/

ただし、複数のファイルを移動しようとすると、いくつかの調整が必要になる場合があります。これが例です(bashで動作しますが、他のシェルの保証はありません):

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
}

まあ...それは私が思っていたより少し長いですが、それは仕事をするはずです

編集: Sebastian Piech コメントで指摘されているように、cpmvの仕事をするのに、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

ただし、これは$PWDの値にlotを依存しているため、使用する場合は十分に注意してください。

9
John WH Smith