複数のディレクトリに複数のファイルを含むディレクトリ構造があります.txt
。.txt
これらすべてのファイルを特定のディレクトリにコピーしたいと思います。以下に私のディレクトリ構造を指定しました。
Dir_1
a.txt
x.doc
b.txt
Dir_2
c.txt
Dir_3
d.txt
e.txt
y.doc
.txt
すべてのファイルをディレクトリにコピーするには、~/alltxt
次のcp
コマンドを使用します。
find . -name "*.txt" -exec cp {} ~/alltxt/ \;
それは非常にうまく動作します。今私のディレクトリはalltxt
次のようになります。
alltxt
a.txt
b.txt
c.txt
d.txt
e.txt
.txt
しかし、変更されたファイルだけがそのフォルダに置き換えたいと思いました。そのためrsync
、次のコマンドを使用すると、これを行うことができることがわかりました。
find . -name '*.txt' -exec rsync -R {} ~/alltxt/ \;
.txt
ただし、以下のようにフォルダごとにファイルをコピーします。
alltxt
Dir_1
a.txt
x.doc
b.txt
Dir_2
c.txt
Dir_3
d.txt
e.txt
y.doc
rsync
しかし、私のコマンドのように動作するようにコマンドをどのように変更できますかcp
?
ベストアンサー1
rsync
--existing
ターゲットにまだ存在しないファイルをコピーしないフラグがあります。
find . -type f -name '*.txt' -exec rsync --existing {} "$HOME/alltxt/" ';'
-type f
また、次の項目のみを検索find
するように追加しました。一般ファイル、この場合には有用ではないと思うので-R
フラグ( --relative
) を削除しました(このフラグを使用するとターゲットにサブディレクトリが生じる理由でもあります)。rsync
私もそれが良く見えると思うので、$HOME
代わりに使用します。~
所有権や変更時間などを保存するために、呼び出しに-a
(--archive
)を追加することもできます。rsync
同様の方法ですが、cp
代わりに使用されますrsync
。
find . -type f -name '*.txt' \
-exec sh -c 'for n; do d="$HOME/alltxt/${n##*/}"; [ -f "$d" ] && cp "$n" "$d"; done' sh {} +
これはすべての.txt
ファイルを見つけ、短いシェルスクリプトを呼び出します。
for n; do
d="$HOME/alltxt/${n##*/}"
[ -f "$d" ] && cp "$n" "$d"
done
このループはここから多くの.txt
ファイルをインポートしますfind
。これらの名前ごとにn
宛先ファイルパスを作成し、d
そのパスが既存の一般ファイルを参照していることを確認し、その場合は指定されたファイルをそこにコピーします。
ターゲットファイルが存在し、見つかったファイルより古い場合は、[ -f "$d" ]
代わりにこのテストを使用できます。[ "$d" -ot "$n" ]
これは非標準テストですが、ほとんどのシェルでサポートされています。
変数置換はパス${n##*/}
からディレクトリを削除することによって(basename)にn
なります。で置き換えることができます。./some/path/file.txt
file.txt
$(basename "$n")