web-dev-qa-db-ja.com

個々の出力行を変数に保存する

過去24時間以内に変更されたファイルを見つけるためにfind -mtime -2を使用しています。出力は次のようになります。

/home/user/logs/file-2014-08-22.log
/home/user/logs/file-2014-08-23.log

出力の1行目を変数に保存してから、2行目を別の変数に保存する必要があります。私はそれを単にパイプすることはできません。 | grep 22または23をお勧めするかもしれませんが、これは何度も実行されるbashスクリプトの一部です。次回は異なる名前の異なるファイルセットがあるため、grep具体的すぎるでしょう。 awkはこれを達成できますか?もしそうなら、どのように? 。

2
chubby_monky

ファイル名にスペースなどがないと仮定すると、これにはいくつかの方法があります。 1つは、配列を使用することです。

files=( $(find -mtime -2) )
a=${files[1]}
b=${files[2]}

filesは、ゼロからインデックス付けされた、findによって出力されたすべてのパスの配列です。あなたはそれからあなたが望むどんな線でも得ることができます。ここでは、2行目と3行目をabに保存しましたが、配列要素を直接使用することもできます。

GNU printfオプションで検索または別のものがある場合の代替手段は、 read および プロセス置換 と組み合わせて使用​​することです。

read junk a b junk < <(find -printf '%p ')

これは、findのすべての出力を単一の行に変換し、その行をreadへの入力として提供します。これにより、最初のワード(パス)がjunk,に保存され、2番目はaに、3番目はbに保存され、残りは再びjunkへの行。

同様に、POSIX互換システムで同じ効果を得るには、 pasteコマンド を導入できます。

read junk a b junk < <(find -mtime -2 | paste -s)

paste -sは、入力を単一のタブ区切り行に変換します。これは、readが再度処理できます。

一般的なケースでは、メインコマンドを複数回実行することに満足している場合(ここでは必要ありません)、 sed を簡単に使用できます。

find | sed -n 2p

これにより、通常の出力を-nで抑制し、2行目をprintに選択することにより、出力の2行目のみが出力されます。 headtailをつなぎ合わせて同じ効果を出すこともできます。これは、非常に長いファイルでより効率的になる可能性があります。

上記のすべては、2行目と3行目をabに格納するのと同じ効果がありますが、スペース、タブ、改行、またはその他の文字がたまたま含まれていないことを前提としています 入力フィールド区切り記号(IFS 任意のファイル名の値。


ただし、 find の出力順序は定義されていないため、他の方法で順序付けするように整理しない限り、「2番目のファイル」は実際には便利な識別子ではありません。多くの場合、作成順序に近いものになる可能性がありますが、すべてではありません。

7
Michael Homer

bash 4.x、使用できます mapfile

$ mapfile -t <<< "$(find -mtime -2)"
$ printf "%s\n" "${MAPFILE[0]}"
/home/user/logs/file-2014-08-22.log
$ printf "%s\n" "${MAPFILE[1]}"
/home/user/logs/file-2014-08-23.log

mapfileは、標準入力からインデックス付き配列変数に行を読み取ります。デフォルトの配列はMAPFILEです。配列の名前を指定できます。

mapfile -t array <<< "$(find -mtime -2)"

-t option cause mapfileは、読み取られた各行から末尾の改行を削除します。

5
cuonglm

コードまたはコマンドラインで見つかった既知の数のファイルまたは繰り返しエントリに制限することなく、次の1行(長い行ですが)を使用して、findの各出力に順次変数名を割り当てることができます。

行/スクリプト:

$ counter=0; for log_file in $(find -mtime -2); do echo $log_file; if [ -f $log_file ]; then ((counter++)); eval var_$counter=`readlink -f $log_file`; fi; done

find行が削除されていない場合の出力(通常のechoのように):

.
./logs
./logs/file-2014-08-22.log
./logs/file-2014-08-23.log

ただし、ここではif -f ....オプションを使用して有効なファイルをスクリーニングします(説明されているように ここ )。したがって、必要な情報が保持されます。

$ echo $counter
2
$ echo $var_1
/home/shadowe/Videos/logs/file-2014-08-22.log
$ echo $var_2
/home/shadowe/Videos/logs/file-2014-08-23.log

したがって、シーケンシャル変数にはfind結果の絶対パスが含まれており、既存のスクリプトに簡単に組み込むことができます。

1
Simply_Me