1

見つけて新しい場所にコピーする必要があるフォルダのリストが表示されました。

私は bash の基本的な知識があり、見つけてコピーするスクリプトを作成しました。

私が使用している基本的なコマンドは、ある程度機能しています。

find ./ -iname "*searchString*" -type d -maxdepth 1 -exec cp -r {} /newPath/ \;

解決したい問題は、見つかった各フォルダーに必要なファイルが含まれていますが、不要なサブフォルダーも含まれていることです。

見つかったフォルダーのルート レベルにあるファイルのみがコピーされるように再帰を制限する方法はありますか。その中のすべてのサブディレクトリとファイルは無視する必要があります。

前もって感謝します。

4

3 に答える 3

0

-R を削除すると、cp はディレクトリをコピーしません。

cp *searchstring*/* /newpath

上記のコマンドは dir1/file1 を /newpath/file1 にコピーしますが、次のコマンドはそれを /newpath/dir1/file1 にコピーします。

  • cp --parents *searchstring*/*(.) /newpath
    • GNU cp および zsh 用
    • . zshの通常のファイルの修飾子です
    • cp --parents dir1/file1 dir2GNU cp で file1 を dir2/dir1 にコピーします
  • t=/newpath;for d in *searchstring*/;do mkdir -p "$t/$d";cp "$d"* "$t/$d";done
  • find *searchstring*/ -type f -maxdepth 1 -exec rsync -R {} /newpath \;
    • -R (--relative) は GNU cp の --parents に似ています
  • find . -ipath '*searchstring*/*' -type f -maxdepth 2 -exec ditto {} /newpath/{} \;
    • 同上はOS Xでのみ利用可能です
    • ditto file dir/filedir が存在しない場合は作成します
于 2013-10-30T15:09:33.953 に答える
0

つまり...フォルダのリストが表示されます。おそらくテキストファイルで?例は提供していませんが、名前の衝突はないとコメントで述べています。

1 つのオプションはrsync、ほとんどのバージョンの Unix および Linux でアドオン パッケージとして利用できる を使用することです。Rsync は基本的に高度なコピー ツールです。1 つ以上のソースと宛先を指定すると、物事が確実に同期されます。物事を再帰的にコピーする方法を知っていますが、その再帰を特定の深さに制限するように指示することはできないため、次は指定されたアイテムをターゲットにコピーしますが、再帰的にコピーします。

xargs -L 1 -J % rsync -vi -a % /path/to/target/ < sourcelist.txt

sourcelist.txt にの行が含まれている場合/foo/bar/slurmslurmディレクトリ全体が にコピーされ/path/to/target/slurm/ます。ただし、これには、 に含まれるディレクトリが含まれますslurm

これは、bash だけでなく、ほぼすべてのシェルで機能します。ただし、sourcelist.txt の行の 1 つに空白やさまざまな特殊文字が含まれていると失敗します。そのため、ソース (コマンド ラインまたは sourcelist.txt 内) が正しくフォーマットされていることを確認することが重要です。また、ソース ディレクトリに末尾のスラッシュが含まれている場合、rsync の動作は異なります。man ページを読んで、必要な動作を決定する必要があります。

入力ファイルは、sh または bash でかなり簡単にサニタイズできます。例えば:

#!/bin/sh

# Avoid commented lines...
grep -v '^[[:space:]]*#' sourcelist.txt | while read line; do

    # Remove any trailing slash, just in case
    source=${line%%/}

    # make sure source exist before we try to copy it
    if [ -d "$source" ]; then
        rsync -vi -a "$source" /path/to/target/
    fi

done

しかし、これはまだrsyncの-aオプションを使用しており、再帰的にコピーします。

rsync だけを使用してこれを行う方法がわかりません。Rsync には-depthオプションがありませんfind。しかし、これを 2 つのパスで行うことがわかります。1 回目はすべてのディレクトリをコピーし、もう 1 回は各ディレクトリからファイルをコピーします。

そのため、例を作成し、フォルダー名にスペースや改行などの特殊文字が含まれていないと仮定します。 (これは重要。)

まず、すべてのディレクトリ自体を再帰的にコピーするのではなく、1 パスでコピーしてみましょう

xargs -L 1 -J % rsync -vi -d % /path/to/target/ < sourcelist.txt

この-dオプションは、sourcelist.txt で指定されたディレクトリーが存在する場合、それを作成します。

次に、ソースのリストを見てみましょう。それぞれをコピーします。

# Basic sanity checking on input...
grep -v '^[[:space:]]*#' sourcelist.txt | while read line; do

    if [ -d "$line" ]; then

        # Strip trailing slashes, as before
        source=${line%%/}

        # Grab the directory name from the source path
        target=${source##*/}

        rsync -vi -a "$source/" "/path/to/target/$target/"

    fi 

done

$sourcersync 行の末尾のスラッシュに注意してください。これにより、rsyncは directory ではなく、ディレクトリ内容をコピーします。

これはすべて意味がありますか?それはあなたの要件に合っていますか?

于 2013-11-02T17:06:27.037 に答える
-1

find のipath引数を使用できます。

find . -maxdepth 2 -ipath './*searchString*/*' -type f -exec cp '{}' '/newPath/' ';'

パスが./find の検索ディレクトリに一致するように で始まり/*、最上位ディレクトリのファイルを除外するためにで終わり、 maxdepth1 レベルの深さだけを再帰するために 2 に設定されていることに注意してください。

編集:

コメントを読み直すと、コピー元のディレクトリを保持したいようですね? たとえば、次を検索する場合foo*:

  • ./foo1/* ---> /newPath/foo1/* にコピー (/newPath/* ではなく)
  • ./foo2/* ---> /newPath/foo2/* にコピー (/newPath/* ではなく)

また、もう 1 つの要件はmaxdepth、速度上の理由から 1 を維持することです。

(コメントで指摘されているように、次の解決策には特別に細工された名前のセキュリティ上の問題があります) 両方を組み合わせて、これを使用できます:
find 。-maxdepth 1 -type d -iname ' searchString ' -exec sh -c "mkdir -p '/newPath/{}'; cp "{}/*" '/newPath/{}/' 2>/dev/null" ';'

編集2:

find完全に捨てて、純粋なbashソリューションを使用してみませんか。

for d in *searchString*/; do mkdir -p "/newPath/$d"; cp "$d"* "/newPath/$d"; done

/検索文字列の末尾にある に注意してください。これにより、ディレクトリのみが一致すると見なされます。

于 2013-10-30T15:32:03.710 に答える