ソースと宛先が類似している場合、bash でワイルドカード拡張を使用する最適な方法は何ですか?

ソースと宛先が類似している場合、bash でワイルドカード拡張を使用する最適な方法は何ですか?

次のようなフォルダがあるとします。

$ ls
css-tricks/ django-tutorial/ good-tuts.txt js-tut/ tutorials/ tuts.txt

これらの中には、名前に が含まれているものがあります。名前に が含まれているすべてのファイル/フォルダをフォルダにtut移動したいと思います。次のコマンドを実行すると、tuttutorials/

$ mv *tut* tutorials/

次のメッセージが表示されます:

mv: cannot move 'tutorials' to a subdirectory of itself, 'tutorials/tutorials'

このようなシナリオを回避するにはどうすればよいでしょうか?


私が思いつくトリックの 1 つは、宛先フォルダーの名前を一時的に別の名前に変更し、コマンドの実行後に希望の名前に戻すことです。ただし、この問題に対するよりエレガントな解決策を知りたいと思っています。

答え1

個人的には、対話的にコマンドを実行しようとしている状況では、単に実行してmv *tut* tutorials「移動できません」というエラーが表示されることを期待します。これは無害であり、他のファイルとディレクトリは期待どおりに移動されます。

コマンドの終了ステータスはゼロ以外になり、エラーを示しますが、これに依存するものは何もないので無視できます。


この場合、他の名前の前にはダッシュが含まれますtut

mv *-tut* tutorials

python_tutまたは、移動したいものがある場合は、アンダースコアも許可します。

mv *[_-]tut* tutorials

または、部分文字列の前に追加の文字を要求するにはtut(これにはtutorials文字がありません)、

mv *?tut* tutorials

もう少し入力して考えながら、拡張グロブ パターンを使用しますbash

shopt -s extglob
mv *tut!(orials*) tutorials

tutこの 2 番目のバリエーションは、直後に文字列が続かない部分文字列を含むものすべてに一致しますorials。パターンは一致せずtutorials、スキップtutorials1なども行われます。

答え2

以下も使用できますfind:

find . -type d -name "*tut*" -not -path "./tutorials" -exec mv -t "tutorials" {} +

答え3

次のメッセージが表示されます:

mv: cannot move 'tutorials' to a subdirectory of itself, 'tutorials/tutorials'

エラーは無視してください。

いや、本当です。glob パターンがターゲットに一致するので、エラーが発生することはわかっています。また、システムはディレクトリをそれ自体の内部で移動できないため、それが何の意味も持たないこともわかっています。システムは、ファイルシステムを台無しにする前にそれを認識できるほど賢いです。

答え4

最も簡単な方法は、ターゲット ディレクトリの名前をtutorials/ファイル名の拡張と一致しない別の名前に変更し、移動を実行した後に希望の名前に変更することです。

関連情報