だから、私はこのようなディレクトリ構造を持っています:
parent/
├── sub1
│ └── source
│ └── file1
│ └── file2
├── sub2
│ └── sub2.1
│ └── source
│ └── something1
│ └── something2
└── sub3
└── sub3.1
└── sub3.1.1
└── source
└── other.Zip
すべてのファイル(異なるファイル名)をsource
という名前のすべてのディレクトリの相対的な上位/親ディレクトリに移動したい。したがって、結果は次のようになります。
parent/
├── sub1
│ ├── file1
│ ├── file2
│ └── source
├── sub2
│ └── sub2.1
│ ├── something1
│ ├── something2
│ └── source
└── sub3
└── sub3.1
└── sub3.1.1
├── other.Zip
└── source
これを達成する簡単な方法(one liner)はありますか、おそらくfind
コマンドを使用しますか?できれば、私にとって理解するには複雑すぎないものをお勧めします。 :D私はLinuxが初めてです。
編集:ソリューションからbashスクリプトを作成します(そのため、簡単に使用できます)。例:./movefiles.sh myfolder
それで、できれば、ソリューションは、umm変数、特に.
(隠しディレクトリの場合)、#
、@
などのシンボルを持つ変数に簡単に対応できます。
find
ソリューションが必要な場合は、これを使用できます。
find parent -name "source" -type d -exec bash -c 'cd "$1"; mv * ..' bash {} \;
説明:
find parent -name "source" -type d
-source
のparent
という名前のディレクトリごとに...-exec bash -c '...' bash {} \;
-$0
としてbash
として$1
としてディレクトリパスを使用してBashを呼び出しますcd "$1"; mv * ..
-ディレクトリにcd;すべてのコンテンツを1レベル上に移動します。mv "$1"/* "$1/.."
これは、多かれ少なかれ デザートの答え に基づいています。
find parent -name "source" -type d -exec bash -c 'shopt -s dotglob; cd "$1"; mv * ..' bash {} \;
shopt -s dotglob
-グロブに隠しファイルを含めるサプライズがあるかもしれないこうした種類のタスクの場合、最良の方法の1つは "script-a-script"です。タスクを実行するために、通常非常に反復的なスクリプトを出力するコマンドを実行します。それが正しいことに満足したら、それをsh
にパイプして実行します。これは複雑な問題をはるかに単純な編集問題に変え、それは非常に一般的な手法であり、この厄介ないくつかのファイルの二階上の問題だけでなく、あらゆる種類の問題に適用できます。これには、エキゾチックなシェル構造を使用しないという利点があり、すべてのシェルで機能します(純粋なPosix sh
、bash
、csh
など)。実行される前にすべての基本的なコマンドが表示されるため、これは"look-before-you-leap"の良い例です。
まず、変更するすべてのディレクトリを見つけます。
$ find . -type d -name source
これは与える
./sub3/sub3.1/sub3.1.1/source
./sub2/sub2.1/source
./sub1/source
次に、コンテンツを1つのディレクトリに移動するディレクトリごとに、実行するコマンドを考えます。
$ mv $dir/* $dir/..
awk
(またはsed
など)を使用してコマンドを記述します。したがって、ディレクトリのリストをawkにパイプします。
$ find . -type d -name source \
| awk '{printf("mv %s/* %s/..\n", $0, $0);}'
mv ./sub3/sub3.1/sub3.1.1/source/* ./sub3/sub3.1/sub3.1.1/source/..
mv ./sub2/sub2.1/source/* ./sub2/sub2.1/source/..
mv ./sub1/source/* ./sub1/source/..
コマンドが正しいことがわかるまで、必要な回数だけ慎重に編集します。
次に、それらすべてをsh
にパイプして実際に実行します。
$ find . -type d -name source \
| awk '{printf("mv %s/* %s/..\n", $0, $0);}' \
| sh
最終出力が何をしているのかを言って、最初のエラーで終了することがよくあるので、sh -e -x
を使用します。
$ find . -type d -name source \
| awk '{printf("mv %s/* %s/..\n", $0, $0);}' \
| sh -e -x
この編集でawk
に自信がない場合は、sed
または純粋なfind
でそれを行うことができます
find . -type d -name source | sed 's|\(.*\)|mv \1/* \1/..|' # sed
find . -type d -name source -exec echo 'mv {}/* {}/..' ';' # find/echo
以下のコードを使用して、必要なものを取得できます。
dir=$(find . -name 'source' | sed s:source::)
for path in $dir; do
mv "$path"source/* "$path"
done
find
コマンドは、親からソースディレクトリへのディレクトリパスを返します。このfind . -name 'source'
'。'は親ディレクトリを表し、「ソース」は検索するサブディレクトリを表します。
sed
コマンドは、source
コマンドの結果からfind
を削除します。
そして、残りは単なる反復(for
)と移動コマンド(mv
)です。
ネストされたfindコマンドは1行でジョブを実行しますが、これは少し風変わりに見えるかもしれません。 ;-)
具体的には:
find . -name source -type d -exec sh -c 'find "$0" -type f -execdir mv "{""}" .. \;' {} \;
find . -name source -type d
は、現在の(.
)ディレクトリーでsource
という名前のすべてのディレクトリーを検出します。
-exec sh -c '...' {} \;
は、見つかったすべてのディレクトリに対してコマンド'...'
でsh
を実行し、ディレクトリ名を{}
にプラグインし、さらに、実行されたsh
の変数$0
を{}
の内容で定義します(sh
マンページのオプション-c
を参照)
sh -c
への引数、'find "$0" -type f ... '
は、ディレクトリ$0
内のすべてのファイルを検索します
最後に、... -execdir mv "{""}" ..
は、見つかったファイル{}
(ここでは、上流の"{""}"
による置換を防ぐために-exec
として非表示)を(ディレクトリローカル-したがって-execdir
)親ディレクトリ..
に移動します
marcus@gargabuntu:~/temp$ tree
.
├── sub1
│ └── source
│ ├── file1
│ └── file2
├── sub2
│ └── sub2.1
│ └── source
│ ├── something1
│ └── something2
└── sub3
└── sub3.1
└── sub3.1.1
└── source
└── other.Zip
9 directories, 5 files
marcus@gargabuntu:~/temp$ find . -name source -type d -exec sh -c 'find "$0" -type f -execdir mv "{""}" .. \;' {} \;
marcus@gargabuntu:~/temp$ tree
.
├── sub1
│ ├── file1
│ ├── file2
│ └── source
├── sub2
│ └── sub2.1
│ ├── something1
│ ├── something2
│ └── source
└── sub3
└── sub3.1
└── sub3.1.1
├── other.Zip
└── source
9 directories, 5 files
シンプルなもの
dir='source'
for i in `find . -name "*" | grep $dir/*| grep -v "$dir$"`; do
mv "$i" "${i%$dir/*}"
done
テスト
$ cd Desktop/test/
/Desktop/test$ tree
.
├── sub1
│ └── source
│ ├── file1
│ └── file2
├── sub2
│ └── sub2.1
│ └── source
│ ├── something1
│ └── something2
└── sub3
└── sub3.1
└── sub3.1.1
└── source
└── other.Zip
9 directories, 5 files
/Desktop/test$ dir='source'
/Desktop/test$ for i in `find . -name "*" | grep $dir/*| grep -v "$dir$"`; do
> mv "$i" "${i%$dir/*}"
> done
/Desktop/test$ tree
.
├── sub1
│ ├── file1
│ ├── file2
│ └── source
├── sub2
│ └── sub2.1
│ ├── something1
│ ├── something2
│ └── source
└── sub3
└── sub3.1
└── sub3.1.1
├── other.Zip
└── source
9 directories, 5 files
/Desktop/test$