すべてのファイル(非表示を含む)をあるディレクトリから別のディレクトリに移動するにはどうすればよいですか?


133

ディレクトリ内のすべてのファイル(隠しファイルを含む)を別のディレクトリに移動するにはどうすればよいですか?

たとえば、ファイル「.hidden」と「notHidden」が含まれるフォルダー「Foo」がある場合、両方のファイルを「Bar」という名前のディレクトリに移動するにはどうすればよいですか?「.hidden」ファイルは「Foo」のままなので、以下は機能しません。

mv Foo/* Bar/

自分で試してみてください。

mkdir Foo
mkdir Bar
touch Foo/.hidden
touch Foo/notHidden
mv Foo/* Bar/


ああ、入力する前に答えを更新する必要があることはわかっていました。非常に役立つリンク。
スティーブンD

悲しいことに、この質問はここで終わったので、ここで移動するか、SUに移動するように言ったので、もちろん、SUにすでに重複があったときにここに移動しました:)
Michael Mrozek

個人的には、* nix固有の質問と回答はSUのトピック外であると思います。現在のルールでは、この質問のように、両者の間で大量のコンテンツの衝突が発生します。
コリークライン

回答:


153

Zsh

mv Foo/*(DN) Bar/

または

setopt -s glob_dots
mv Foo/*(N) Bar/

(N)ディレクトリが空でないことがわかっている場合は省略します。)

バッシュ

shopt -s dotglob nullglob
mv Foo/* Bar/

Ksh93

ディレクトリが空でないことがわかっている場合:

FIGNORE='.?(.)'
mv Foo/* Bar/

標準(POSIX)sh

for x in Foo/* Foo/.[!.]* Foo/..?*; do
  if [ -e "$x" ]; then mv -- "$x" Bar/; fi
done

mvコマンドが成功したとしてもエラーステータスを返すようにする場合は、はるかに簡単です。

mv Foo/* Foo/.[!.]* Foo/..?* Bar/

GNU findおよびGNU mv

find Foo/ -mindepth 1 -maxdepth 1 -exec mv -t Bar/ -- {} +

標準検索

ソースディレクトリに変更してもかまわない場合:

cd Foo/ &&
find . -name . -o -exec sh -c 'mv -- "$@" "$0"' ../Bar/ {} + -type d -prune

ここでは、bash、ksh93、zshでドットファイルを一致させるかどうかの制御について詳しく説明します。

バッシュ

dotglobオプションを設定します

$ echo *
none zero
$ shopt -s dotglob
$ echo *
..two .one none zero

また、より柔軟なGLOBIGNORE変数があり、これをコロンで区切ったワイルドカードパターンのリストに設定して無視できます。設定されていない場合(デフォルト設定)、シェルは値がdotglob設定されている場合は値が空であるかのように動作し.*、オプションが設定されていない場合は値があるかのように動作します。マニュアルのファイル名拡張を参照してください。パーベイシブディレクトリ....、パターンで明示的に一致しない限り、常に省略されます。

$ GLOBIGNORE='n*'
$ echo *
..two .one zero
$ echo .*
..two .one
$ unset GLOBIGNORE
$ echo .*
. .. ..two .one
$ GLOBIGNORE=.:..
$ echo .*
..two .one

Ksh93

FIGNORE変数を設定します。設定しない場合(デフォルト設定)、シェルは値がであるかのように動作します.*。とを無視する.には..、それらを明示的に一致させる必要があります(ksh 93s + 2008-01-31のマニュアルでは、...は常に無視されていますが、実際の動作については正しく説明されていません)。

$ echo *
none zero
$ FIGNORE='@(.|..)'
$ echo *
..two .one none zero
$ FIGNORE='n*'
$ echo *
. .. ..two .one zero

ドットファイルを明示的に照合することで、パターンに含めることができます。

$ unset FIGNORE
$ echo @(*|.[^.]*|..?*)
..two .one none zero

ディレクトリが空の場合に展開を空にするには、Nパターンマッチングオプション:~(N)@(*|.[^.]*|..?*)またはを使用します~(N:*|.[^.]*|..?*)

Zsh

dot_globオプションを設定します

% echo *
none zero
% setopt dot_glob
% echo *
..two .one none zero

.そして..パターンが有力と一致した場合でも、一致されることはありません.明示的に。

% echo .*
..two .one

D glob修飾子を使用すると、特定のパターンでドットファイルを含めることができます。

% echo *(D)
..two .one none zero

Nglob修飾子を追加して、空のディレクトリで展開が空になるようにします*(DN)


注意:あなたは、(例えば、異なる順序でファイル名展開の結果を得ることnoneが続く.one続く..twoの設定に基づいて)LC_COLLATELC_ALLおよびLANG変数。


1
なんでnullglob?あまり意味のないコマンドを実行するよりも、mvコマンド(fish、csh / tcsh、zsh(なし(N))do、またはfailglob付きbashなど)を中止する方が理にmv /Bar/かなっています。
ステファンシャゼラス

1
GLOBIGNOREの説明は不正確で誤解を招くと思います。GLOBIGNOREを空でない値に設定すると...dotglobがオンになり、後でdotglobをオフに戻しても、(zsh、fish、pdksh、および派生物などの他の賢明なシェルのように)dotglobがオンになり、一致しません。(GLOBIGNORE=:; shopt -u dotglob; echo .*出力.しません..)。GLOBIGNOREを設定する.:..か、.または:同じ効果があります。
ステファンシャゼラス

ksh93常に無視し.、(動作した場所)と(動作しなくなった場所)の..間で壊れているようです。環境からFIGNOREの値を取得するという点で悪いことに注意してください。そのため、たとえばenv varは大混乱を引き起こす可能性があります。ksh93k+ksh93mksh93FIGNORE='!(..)'
ステファンシャゼラス

24
#!/bin/bash

shopt -s dotglob
mv Foo/* Bar/

から man bash

dotglob設定されている場合、bashには「。」で始まるファイル名が含まれます パス名展開の結果。


ディレクトリが空の場合、このコマンドはエラーコードを返すことに注意してください(コマンドが実際に意図したとおりに実行された場合でも)。
ジル

1
@Gillesの場合、エラーは、mv呼び出されたファイルFoo/*が存在しないという苦情によるものです。興味深いことに、Foo検索可能ではあるが、読み取り可能ではなく、そこにファイルが呼び出さ*れている場合、エラーは発生せず、そのファイルは移動されますが、ディレクトリ内の他のファイルは移動されません。bash持っているfailglob、それはより多くのように振る舞うように、オプションをzshfishまたはcsh/ tcshおよびグロブではなく、そのままでグロブを残すこと偽の振る舞いを拡張することはできませんエラーでコマンドを中止します。
ステファンシャゼラス

8

これを行う簡単な方法bash

mv {Foo/*,Foo/.*} Bar/

ただし、これによりディレクトリも移動します。

hiddenを含むすべてのファイルを移動したいが、ディレクトリを移動したくない場合は、forループとテストを使用できます。

for i in $(ls -d {Foo/*,Foo/.*});do test -f $i && mv -v $i Bar/; done;


4

1つの方法は使用することfindです:

find Foo/ -type f -exec mv -t Bar/ {} \+

-type f、検索コマンドをファイルの検索に制限します。あなたが調査する必要があり-type-maxdepth-mindepthのオプションは、findサブディレクトリのためのアカウントにコマンドをカスタマイズします。Findには、長くても非常に役立つマニュアルページがあります


3
それはFoo/、サブディレクトリや他のファイルではなく、通常のファイルのみを移動します。
ジル

2

コピーコマンドを試してくださいcp

$ cp -r myfolder/* destinationfolder

cp -r は再帰的なコピーを意味するため、すべてのフォルダーとファイルがコピーされます。

removeコマンドrmを使用して、フォルダーを削除できます。

$ rm -r myfolder

詳細:すべてのファイルをディレクトリから別のディレクトリに移動します


2
大量の大きなファイルを移動する場合は最適ではありませんが、うまくいくと思います。
コリークライン

たぶん、星の代わりにドットを使うとしたら?
ヴィンセント

1

Rsyncは別のオプションです。

rsync -axvP --remove-source-files sourcedirectory/ targetdirectory

これは、rsyncでは末尾のスラッシュが重要でsourcedirectory/あり、ディレクトリのコンテンツをsourcedirectory参照し、ディレクトリ自体を参照するためです。

この方法の欠点は、rsyncがディレクトリを移動するのではなく、移動後にファイルのみをクリーンアップすることです。したがって、空のソースディレクトリツリーが残ります。そのための回避策については、以下を参照してください。

rsyncでファイルを移動してディレクトリを削除しますか?

したがって、これは移動操作には最適ではないかもしれませんが、コピー操作には非常に便利です。


1

bash / fishの回答

ワイルドカードを使用してこれを行う方法は次のとおりです。

.[!.]* ..?*一致するすべての隠しファイルを除き...

.[!.]* ..?* *一致するすべてのファイルを(隠したりしない)を除く.と、..

そして、この質問の特定の例に答えるために必要です cd foo && mv .[!.]* ..?* * ../bar

説明

.[!.]*1つのドットで始まり、オプションで任意の文字列が続くドットを除く任意の文字が続くファイル名に一致します。これは十分に近いですが、のような2つのドットで始まるファイルを見逃しています..foo。このようなファイルを含めるには..?*、2つのドットで始まり、その後に任意の文字、オプションで任意の文字列が続くファイル名に一致するファイルを追加します。

テスト

以下のコマンドを使用して、これらのワイルドカードをテストできます。私はそれらをバッシュとフィッシュの下でうまく試しました。sh、zsh、xonshの下で失敗します。

mkdir temp
cd temp
touch  a  .b  .bc  ..c  ..cd  ...d  ...de
ls .[!.]* ..?*
# you get this output:
          .b  .bc  ..c  ..cd  ...d  ...de
# cleanup
cd ..
rm -rf temp

0

また、逆引用符で検索してgrepを実行し、moveコマンドのファイルを選択できる場合もあります。それらをmvに渡します。

すなわち、隠しファイルの場合

find Foo -maxdepth 1 | egrep '^Foo/[.]' # Output: .hidden

そう

mv `find Foo -maxdepth 1 | egrep '^Foo/[.]'` Bar # mv Foo/.hidden Bar

選択した隠しファイルのみをに移動しますBar

mv `find Foo -maxdepth 1 | egrep '^Foo/.'` Bar # mv Foo/.hidden Foo/notHidden Bar

「。」以降、Fooのすべてのファイルをバーに移動します egrepコマンドでは、角括弧なしのワイルドカードとして機能します。

この^文字により、一致は行の先頭から開始されます。

egrepパターンマッチングの詳細についてはこちらをご覧ください

maxdepth 1ストップを使用すると、サブディレクトリに移動できません。


0

この答えに触発された:

ファイルをコピーせずに...

rsync -ax --link-dest=../Foo/ Foo/ Bar

警告:

  • --link-destパスは、DESTINATIONに対する絶対パスまたは相対パスである必要があります(Bar 例では)

  • /SOURCEの後に置くFoo/必要があります(この例では)。そうしないと、SOURCEフォルダーの内容ではなくSOURCEフォルダーがコピーされます。


0

これはbashでうまく機能し、シェルオプションを変更する必要がないことがわかりました

mv sourcedir/{*,.[^.]*} destdir/

編集:

G-manが述べたように、私の元の答えはposixに準拠しておらず、上記のndemouの答えとほとんど同じですが、1つの変更点があります。これは単にあなたがする必要がないことを意味しますcd、ソースディレクトリに移動。それほど大きな変化ではありませんが、違いはあります。

例:次のレイアウトが既にあるとしましょう。

 $ tree -a
.
├── destdir
└── sourcedir
    ├── ..d1
    ├── ..d2
    ├── ..double
    ├── file-1
    ├── file-2
    ├── .hidden-1
    ├── .hidden-2
    ├── ...t1
    └── ...t2

元の質問では、ピリオドが1つだけの隠しファイルについて言及していましたが、名前の先頭にピリオドが2つ以上あるものがあるとしましょう。追加の式を中かっこに追加するだけです。その後、実行することができます

mv sourcedir/{*,.[!.]*,..?*} destdir/

これは次のように展開されます。

mv sourcedir/file-1 sourcedir/file-2 sourcedir/.hidden-1 sourcedir/.hidden-2 sourcedir/..d1 sourcedir/..d2 sourcedir/..double sourcedir/...t1 sourcedir/...t2 destdir/

destdirにあるすべてのファイルが表示されるはずです

 $ tree -a
.
├── destdir
   ├── ..d1
   ├── ..d2
   ├── ..double
   ├── file-1
   ├── file-2
   ├── .hidden-1
   ├── .hidden-2
   ├── ...t1
   └── ...t2
└── sourcedir

4.xでは、bashのブレースにさらに追加を加えることで、かなりクールなことができます。気の利いた例については、bash-hackersご覧ください。


1
これは基本的に、中括弧を追加したことを除いて、ndemouの答えを複製します(説明せずに)。ただし、(1)名前がで始まるファイルと一致しない場合..、および(2)POSIX準拠である場合は、!代わりに使用する必要があり^ます。すなわち、  {*,.[!.]*}
G-Man

@ G-Man、ごめんなさい。それであなたは正しいです、そしてndemouの反応を見ないのは私の悪いことです。それらはほとんど同じものです。1.私のバージョンがposixに準拠していないことを指摘していただきありがとうございます。2.ブレース拡張を使用して、シェルがアクションを実行するために使用する文字列のリストを作成しています。これはまたcd、すべてのファイルへのパスを表すために、ファイルを操作したり、同じファイルパスを何度も書き出したりするためにソースディレクトリに移動する必要がないことも意味します。読者に私が話していることをよりよく理解できるように、例をすぐに更新します。
cmndr sp0ck

0

以下のための最小限の Linuxディストリビューション、以下は動作するはず。まず、すべての基本的な移動を実行します(隠しファイルが見つかりません)。次に、(を含むすべての隠しファイルを移動.して..いるだろうではない、実際に移動することを)。

mv /sourceDir/* /destinationDir 2> /dev/null
mv /sourceDir/.* /destinationDir 2> /dev/null

注:表示されるコンテンツがない場合、最初のコマンドはエラーメッセージを生成します。2番目のコマンドはなります常にそれが移動することはできませんというエラーを生成.して..。そのため、エラーをパイプするだけです/dev/null(図を参照)。

ワンライナーとしてこれが必要な場合は、セミコロンと組み合わせてください:

mv /sourceDir/* /destinationDir 2> /dev/null; mv /sourceDir/.* /destinationDir 2> /dev/null
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.