2017-01-04 22 views
0

私は先月に複数のポイントで取り組もうとしてきた問題にどのように接近するかについて質問しました。シナリオはそうのようなものです:すべてのB*はそれらの下pipeline/results/ディレクトリ構造を持っている名前プレフィックスに基づいたgrepファイル

A/{B1,B2,B3}

私はすべて同じサブディレクトリ形式以下の複数のサブディレクトリとベースディレクトリを持っています。

これらのすべてのresultsディレクトリには、複数の*.xyzファイルがあります。これらの*.xyzファイルには、名前付けプレフィックスに基づいて特定の階層があります。名前の接頭辞は、処理された距離によって異なります。例えば、select.xyz,select.copy.xyzおよびselect.copy.paste.xyzであり、操作はselect,copyおよびpasteである。私がしたいのは、処理レベルに基づいてこれらのファイルを選択するls | grepまたはfindです。

EDIT: - >copy - >paste

処理パイプラインはselectを行きます。 「最も処理された」ファイルは、ファイル名に接頭辞としてそれらの段階の大半を持つものです。すなわちselect.copy.paste.xyz

B2/pipeline/results/select.xyz

B3/pipeline/results/を持って、今度は例えばselect.xyz

よりも処理される、のは

B1/pipeline/results/select.xyzselect.copy.xyzを持っているとしましょう、select.copyよりも処理され、select.xyzを持っていますselect.copy.xyzおよびselect.copy.paste.xyz

ls | grep/findは、各サブディレクトリから最も処理されたファイルを選択する方法を教えてください。これは私にB1/pipeline/results/select.copy.xyz,B2/pipeline/results/select.xyzB3/pipeline/results/select.copy.paste.xyzを与えるはずです。

私がアプローチについてどのように考えることができるかについてのあらゆる指針が役立ちます。ありがとうございました!

+1

"最も処理された"とはどういう意味ですか? – codeforester

+1

この例では、「Most processed」が説明されています。しかし、ディレクトリ構造はどうですか? '.xyz'はプレースホルダだけですか? 'select.txt'と' select.html'の2つのファイルのように、同じディレクトリに異なる拡張子を付けることはできますか?そして、A/{B1、B2、B3}のAはどうでしょうか? Aはプレースホルダでもありますか? – Socowi

+0

@codeforester私は謝罪します - 私はそれを明示的にするためにその詳細を追加します。処理パイプラインは 'select'>' copy'> 'paste'となります。 「最も処理された」ファイルは、ファイル名に接頭辞としてそれらの段階の大半を持つものです。 –

答えて

1

この回答では、ディレクトリ構造の上位部分A/B{1,2,3}は無視されます。ディレクトリがA/B1/doNotIncludeMe/forbidden/pipeline/resultsであっても、一部の.../pipeline/results/ディレクトリ内のすべてのファイルが考慮されます。ファイル拡張子xyzは定数であると仮定します。

単純な解決策は、ディレクトリをループしてファイルが先頭から前に存在するかどうかを確認することです。つまり、最初にselect.copy.paste.xyzが存在するかどうかを確認します。ファイルが存在しない場合は、select.copy.xyzなどが存在するかどうかを確認してください。このスクリプトは次のようになります。

#! /bin/bash 
# print paths of the most processed files 

shopt -s globstar nullglob 
for d in **/pipeline/result; do 
    if [ -f "$d/select.copy.paste.xyz" ]; then 
     echo "$d/select.copy.paste.xyz" 
    elif [ -f "$d/select.copy.xyz" ]; then 
     echo "$d/select.copy.xyz" 
    elif [ -f "$d/select.xyz" ]; then 
     echo "$d/select.xyz" 
    else 
     # there is no file at all 
    fi 
done 

これはうまくいきますが、あまりうまくありません。私たちはより良いことができます!

#! /bin/bash 
# print paths of the most processed files 

shopt -s globstar nullglob 
for dir in **/pipeline/result; do 
    for file in "$dir"/select{.copy{.paste,},}.xyz; do 
     [ -f "$file" ] && echo "$file" && break 
    done 
done 

第2のスクリプトは、最初のスクリプトとまったく同じことを行いますが、維持や適応などが容易です。両方のスクリプトは、スペースや改行を含むファイル名とディレクトリ名で動作します。

あなたのパスに空白がない場合は、以下の(ハッキーですがループフリーの)スクリプトを使用することもできます。

#! /bin/bash 
# print paths of the most processed files 

shopt -s globstar nullglob 
files=(**/pipeline/result/select{.copy{.paste,},}.xyz) 
printf '%s\n' "${files[@]}" | sed -r 's#(.*/)#\1 #' | sort -usk1,1 | tr -d ' ' 
+0

ありがとう - これは素晴らしいです。余計なステップがいくつかありますが、それには絶対に価値があります。私はグーグルで、 '{' s}を使ってパラメータ拡張を勉強しました。 'sed'の'# 'を説明してください。私は '' sed'で ''を使ったことは一度もなく、 '' sed''をたくさんしました。編集:NVM私はグーグルで、それは明らかにバックスラッシュと同じ機能を提供します - ちょうど区切り文字: –

+0

'.copy'と' .paste'がアルファベット順に '.xyz'の前にあるので、' sort -u'は機能しますか?拡張子がまだ一定で、 '.fyz'の場合はどうなりますか? –

+1

'sort -u'は' .aaa'でも動作します。 'sort 'の前の' sed'は、ファイルのリストを2つのカラムに分けます:1.ファイル名のないパス、2.ファイル名。最初の列でソートするだけです。つまり、サブディレクトリごとにグループ化します。各グループのファイルの順番は同じです*( '{{{{{{copy {...} '} ...最も処理されたファイルが常に最初に来るように書いています)。 'sort'はすべてのグループの最初の行を選びます。 ---------------------- *実際には、隠れたバグがありました。 'sort'は、等しい行の順序を変えるかもしれません。安定性を確保するために 'sort -s'を使わなければなりません。 – Socowi

関連する問題