コンテンツパターンの一致に基づいてファイルをディレクトリに移動します。

コンテンツパターンの一致に基づいてファイルをディレクトリに移動します。

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と同じ名前の新しいディレクトリに移動し、ファイル名を変更しないでください。

  • つまりfile1file5file6に移動apple
  • file2行くorange
  • file3行くpear
  • など。

ls:

apple pear grapes orange etc ...

./apple:
file1 file5 file6

./pear:
file3

/orange:
file2

次に、新しいサブディレクトリを作成し、field2コンテンツの最初の行が同じファイルをそのサブディレクトリに移動しようとします。

  • ディレクトリの下でappleサブfile1ディレクトリに移動し1file5サブディレクトリに移動し3file6サブディレクトリに移動します。3
  • ディレクトリの下からサブディレクトリに移動しますorangefile22
  • ディレクトリの下からサブディレクトリに移動しますpearfile31
  • など。

ソートおよび移動後、ファイルは次のようにソートする必要があります。

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つの方法の実際の例です。

おすすめ記事