files
特定のコンテンツを含む既存のディレクトリのファイルを呼び出すスクリプトを作成して、既存または新しいディレクトリとサブディレクトリに移動し、そのファイルをdir / subdirに移動したいと思います。fruit
~/bin
files
たとえば、file1 file2 file3.... file100という既存のディレクトリには多くの一般的なファイルがあります。
ls
:
file1
file2
file3
file4
...
file100
ファイルの内容は次のとおりです。
cat file1
apple 1
789098
cat file2
orange 2
389342
cat file3
pear 1
678034
cat file4
grapes 3
123432
cat file5
apple 3
342534
cat file6
apple 3
234298
field1の最初の行が同じファイルをfield1と同じ名前の新しいディレクトリに移動し、ファイル名を変更しないでください。
- つまり
file1
、file5
、file6
に移動apple
file2
行くorange
file3
行くpear
- など。
ls
:
apple pear grapes orange etc ...
./apple:
file1 file5 file6
./pear:
file3
/orange:
file2
次に、新しいサブディレクトリを作成し、field2コンテンツの最初の行が同じファイルをそのサブディレクトリに移動しようとします。
- ディレクトリの下で
apple
サブfile1
ディレクトリに移動し1
、file5
サブディレクトリに移動し3
、file6
サブディレクトリに移動します。3
- ディレクトリの下からサブディレクトリに移動します
orange
。file2
2
- ディレクトリの下からサブディレクトリに移動します
pear
。file3
1
- など。
ソートおよび移動後、ファイルは次のようにソートする必要があります。
ls
:
apple pear grapes orange etc ...
./apple:
1 3
./apple/1:
file1
./apple/3:
file5 file6
./orange:
2
./orange/2:
file2
./pear
1
./pear/1
file3
viエディタを使用してすべてのファイルを繰り返し、それをシェルの対応するディレクトリとサブディレクトリに移動するにはどうすればよいですか?
ベストアンサー1
$ find . -name 'file*'
./file6
./file1
./file5
./file2
./file3
./file4
$ perl -lane '
close(ARGV);
mkdir $F[0] unless -e $F[0];
mkdir "$F[0]/$F[1]" unless -e "$F[0]/$F[1]";
rename $ARGV, "$F[0]/$F[1]/$ARGV" if (-d "$F[0]/$F[1]");
' file*
$ find . -name 'file*'
./pear/1/file3
./grapes/3/file4
./orange/2/file2
./apple/1/file1
./apple/3/file5
./apple/3/file6
file{1..6}
サンプルファイルです。 Perlスクリプトは各ファイルを順番に開き、最初の行を読み取り、それを配列に分割します@F
(Perlの-a
コマンドラインオプションを介して)。その後、ファイルを閉じて(ラインカウンタをリセットする副作用がある$.
)、ディレクトリを作成し(まだ存在しない場合)、ファイルをディレクトリに移動します(実際にディレクトリの場合)。すでに存在する場合は、通常のファイル、シンボリックリンク、またはディレクトリ以外のものかもしれません。
1行以上のファイルは無視されます。予期しない形式のファイル(たとえば、最初の行には、デフォルトのディレクトリ名とサブディレクトリ名を含むすべての種類の空白で区切られた2つのフィールドが含まれています)は定義されていません(おそらく奇妙なことや災害的かもしれません) ) 結果をもたらす可能性があります。
これら 2 つのfind
コマンドは、Perl one-liner を実行する前後のファイルの場所を表示するために使用されます。これは出力を生成しない最小限のスクリプトです。また、エラーチェックやデータ検証も不十分です。
スタンドアロンスクリプトとしての代替バージョンです。この記事を書く唯一の本当の理由は、
Perlオプションに関するStéphaneのコメントを扱うことです-T
(ほとんどの場合問題ではありません...注意してください。/間違ったことはありません。)
$ cat sort-move.pl
#!/usr/bin/perl
use strict;
use File::Path qw(make_path);
while(<<>>) {
my($dir,$subdir) = split;
close(ARGV);
make_path("$dir/$subdir");
rename $ARGV, "$dir/$subdir/$ARGV" if (-d "$dir/$subdir");
}
たとえば、実行してみてください./sort-move.pl file*
。ディレクトリ生成エラーが致命的な条件であることを除いて、結果は1行バージョンとまったく同じです。
追加のエラーチェックやデータ検証は行われません。実際には少ない作業を行います(ディレクトリを作成するためのコアmake_path()
PerlモジュールFile::Path
の機能に依存します。make_path()
非常によく似ていますmkdir -p
)。つまり、悪いデータはまだ悪いことになるので、悪いデータを提供しないでください。
ただし、すでに存在し、ディレクトリではなく(またはファイルシステムスペースの不足やinodeの不足などの他の理由によるエラーのために)失敗した場合、make_path
スクリプトはすぐにエラーメッセージで終了します。"$dir/$subdir"
たとえば、mkdir apple; touch apple/1
以前にこのスクリプトを実行した場合、エラーメッセージは次のようになりますmkdir apple/1: File exists at ./sort-move.pl line 9.
。スクリプトはディレクトリを生成せず、ファイルを移動しません。私はそれをテストするために正確に行ったので、これを知っています。
スクリプト全体がエラー条件を適切に処理します。スクリプト全体にはコンテンツのみを表示する-n
オプションもあります。--dry-run
会議実際にやらずにやってみてください。これは完全なスクリプトではありませんが、最小必要なことを行う1つの方法の実際の例です。