あるディレクトリから別のディレクトリにファイルをマージするシェルスクリプトを探しています。
サンプル:
html/
a/
b.html
index.html
html_new/
a/
b2.html
b.html
使用法:
./mergedirs.sh html html_new
結果:
html/
a/
b.html
b2.html
index.html
html/a/b.html
はhtml_new/a/b.html
に置き換えられましたhtml/a/b2.html
はhtml_new/a/b2.html
からコピーされましたhtml/index.html
はそのまま維持されました
おそらくcp -R $1/* $2/
だけが必要です—これは再帰的なコピーです。
(隠しファイル(名前がドットで始まるファイル)が存在する可能性がある場合、そのコマンドの前にshopt -s dotglob;
を付けて、それらが一致することを確認する必要があります。)
cp -RT source/ destination/
source
内のすべてのファイルとディレクトリはdestination
になります。たとえば、source/file1
はdestination/file1
にコピーされます。
-T
フラグは、代わりにsource/file1
がdestination/source/file1
にコピーされないようにします。
Rsyncを見てみましょう
rsync --recursive html/ html_new/
Rsyncには設定するフラグがたくさんあるので、rsyncのマンページで詳細を確認してください
Rsyncを使用するだけです。これは、リモートコピーに加えて、ローカルファイルのコピーとマージに最適なツールです。
rsync -av /path/to/source_folder/ /path/to/destination_folder/
Source_folderの内容のみを宛先にコピーするには、ソースフォルダーの末尾のスラッシュが必要であることに注意してください。そのままにしておくと、source_folder andの内容がコピーされます。これは、フォルダーをマージするため、おそらく探しているものではありません。
cp -r
は機能しませんか?
cp -r html_new/* html
または(最初のバージョンは「.something」ファイルをコピーしないため)
cd html_new; cp -r . ../html
コピーされたディレクトリ内のファイルのいずれかがパイプである場合、-r
パイプからの読み取りであることに注意してください。それを避けるには、代わりに-R
を使用してください。
cd html
cp -r . /path/to/html_new
この質問とその受け入れられた答えは古くても、cp
を使用する現在存在するものはエッジケースを処理しないか、対話的に作業する必要があるため、答えを追加しています。多くの場合、Edge-cases/scriptability/portability/multiple-sourcesは重要ではありません。その場合、単純さが優先され、認知負荷を減らすために、より少ないフラグでcp
を直接使用することをお勧めします。 other times(または堅牢に再利用可能な関数の場合)この呼び出し/関数は有用であり、偶然にもbash固有ではありません(この質問はbashについてだったので、この場合は単なるボーナスです) 。一部のフラグは省略できます(たとえば、-a
)。ただし、説明のために、すべてを明示的に長い形式(-R
を除く、以下を参照)に含めました。特定の機能がある場合は、フラグを削除するだけですdo n'tが必要です(または、非POS OSを使用している場合、またはcp
のバージョンがそのフラグを処理しない場合-これをテストしました) GNU coreutils 8.25のcp
):
mergedirs() {
_retval=0
_dest="$1"
shift
yes | \
for _src do
cp -R --no-dereference --preserve=all --force --one-file-system \
--no-target-directory "${_src}/" "$_dest" || { _retval=1; break; }
done 2>/dev/null
return $_retval
}
mergedirs destination source-1 [source-2 source-3 ...]
説明:
-R
: この回答 で説明されているように、一部のシステム(特にソースディレクトリの特殊ファイルに関して)で-r
/--recursive
とは微妙に異なるセマンティクスを持ちます。--no-dereference
:SOURCEのシンボリックリンクをたどらない--preserve=all
:指定された属性(デフォルト:mode、ownership、timestamps)を保持し、可能であれば追加の属性:context、links、xattr、all--force
:既存の宛先ファイルを開けない場合は、それを削除して再試行します--one-file-system
:このファイルシステムにとどまる--no-target-directory
:DESTを通常のファイルとして扱います( この回答 で説明されています。つまり、If you do a recursive copy and the source is a directory, then cp -T copies the content of the source into the destination, rather than copying the source itself.
)yes
からの入力をパイプ処理]:--force
でも、この特定の再帰モードでは、cp
は各ファイルを上書きする前に要求するため、yes
からの出力をパイプ処理することで非対話性を実現します/dev/null
]への出力のパイピング:これは、cp: overwrite 'xx'?
の行に沿って乱雑な質問文字列を黙らせるためです。1
が返されますところで:
--reflink=auto
で、いわゆる「ライトコピー」(コピーオンライト、ハードリンクと同じ速度の利点、同じサイズの利点)ファイルが将来どの程度発散するかに反比例するまで)。このフラグは最近のGNU cp
で受け入れられ、最近のLinuxカーネル上の互換性のあるファイルシステムとの何もしない操作を実行します。他のシステム上のYMWV-a-lot。