Linux コマンドで隠しファイルを含んで再帰的に移動・コピーする
Linux コマンドの cp
や mv
で、隠しファイルを含んで複数のファイルを再帰的に移動したりコピーしたりしたかった。具体的には、
/PATH/TO/example-directory/
└ source/
├ .dotfile-1
├ example-file-1.txt
└ sub-directory/
├ .dotfile-2
└ example-file-2.txt
こんな感じで source/
ディレクトリ配下に隠しファイル (ドット .
始まりのファイル) がある状態で、これらを
/PATH/TO/example-directory/
├ source/ ← (移動した場合は空っぽ・コピーの場合はそのまま)
├ .dotfile-1
├ example-file-1.txt
└ sub-directory/
├ .dotfile-2
└ example-file-2.txt
こんな風に一階層上に移動 or コピーしたいなー、と思っていた。
最初に思いつくのは
$ cp -r ./source/* .
こんな書き方だが、コレだと source/sub-directory/.dotfile-2
はコピーされるが、source/
直下にある source/.dotfile-1
がコピーされないようだった。
そこで調べてみると、以下のいずれかの書き方で、source/
直下にある source/.dotfile-1
も含めて再帰的にコピーできるようだった。
# 以下のいずれかのコマンド
$ cp -r ./source/. .
$ cp -a ./source/. .
なんと、アスタリスク source/*
ではなく、ピリオド source/.
を使うようだ。
- 参考 : In bash, cp does copy dot files while using wildcard? Which option should I use - Stack Overflow
検証した限りでは、以下のコマンドは微妙だった。
# 以下の書き方は「一階層上に上げる」時に使うと `..` もコピー対象に扱われてしまいエラーメッセージが出てしまったので微妙
# 別のディレクトリにまるっと移動するなら使えそう
$ cp -r ./source/.[^.]* ./dist/
# 直下の source/.dotfile-1 のみを対象にする書き方
$ cp -r ./{.,}* .
なお、cp -r
や cp -a
は cp
コマンドでしか使えない。mv
の場合は別の方法を使う。
cp
でも mv
でも両方で使えるやり方として、アスタリスクが隠しファイルを含むように shopt
コマンドで設定を変えておく、というやり方がある。コレの方が分かりやすいかも。
# 予め以下の shopt -s コマンドを打っておく
$ shopt -s dotglob
# そうすると、以下のようにアスタリスクを使った cp・mv 時にドットファイルも含んで操作してくれる
$ cp -r ./source/* .
$ mv ./source/* .
# shopt -s コマンドによる設定を元に戻すには以下のように叩く
$ shopt -u dotglob
読んで字の如く、dotglob
はドットファイルも glob 展開の対象にする、というワケ。
- 参考 : SOLVED recursively cp all directories, files and hidden files
- 参考 : ファイル名がドットから始まるファイルをまとめて cp や mv できないときの対処方法 - Qiita
ちなみに、cp
と mv
には -n
オプションがあり、コレを指定するとコピー先・移動先に同名ファイルがあった時に上書きコピー・移動をしなくなる。うっかり上書きしてしまわないようにするには、-n
オプションを使うと良いだろう。