Linuxシェルスクリプトでfindコマンドを使用した条件の場合

Linuxシェルスクリプトでfindコマンドを使用した条件の場合

if条件でfindコマンドを作成しようとしています。まず、要件を共有します。 /tmp/fmxfile というファイルにファイルのリストがあります。

cat /tmp/fmxfile
/fmx/eng/hint.fmx
/pll/case.pll
/plx/eng/case.plx

最初のIF条件では、最初にファイルの上にforループを作成しています(条件が合格すると、別のパスですべてのファイルを検索します)。ファイルがそのパスにあるか、2番目のIF条件にないことを確認したいと思います。過去5分間ファイルが変更されたことを確認し、trueの場合は/tmpパスにファイルをコピーします。

cd /apps/common/bau/base/
for file in `cat /tmp/fmxfileslist`
do
if [ -f $file ]
then
    echo "File '${file}' found in $(pwd) path and created on $(date +%D)."
    if [ $(find $file -mmin -5 -type f) ="true" ];
    then
    cp -a $file /tmp/basefmxfiles
    ls -lrt | grep /tmp/basefmxfiles
    else 
    echo "But the file is not modified in last 5 minutes"
    fi
else
echo "$0: File '${file}' not found."
fi
done

ベストアンサー1

コードのいくつかの説明(sh構文にあると仮定):

cd /apps/common/bau/base/

終了ステータスを確認しないため、cd失敗した場合は、現在の作業ディレクトリで残りのスクリプトを実行し続けます。

for file in `cat /tmp/fmxfileslist`

廃止予定のコマンド置換形式の上に分割+globを使用し、`...`ファイル行を繰り返すように見えますが、構文は次のとおりです。

while IFS= read -r file <&3; do
  ...
done 3< /tmp/fmxfileslist

(または変更する必要があります/tmp/fmxfile)?

/tmpまた、グローバルに書き込み可能なディレクトリに固定名(たとえば)を持つファイルを使用することは、セキュリティの観点から悪い習慣です。

また、例リストのパスのどれも相対パスではないので、現在の作業ディレクトリが何であるかが重要ですか?または、リストは次のようにする必要があります。

fmx/eng/hint.fmx
pll/case.pll
plx/eng/case.plx

代わりに?それとも前に先行を/削除または挿入する必要がありますか?.

do
if [ -f $file ]

これは拡張で再分割+globを使用することですが$file、これは言葉にはなりません。おそらくあなたが意味するのは、[ -f "$file" ]ファイルが存在することを確認することが目的であるかどうか、ファイルにアクセスでき、次に識別できるかどうかです。定期的な(ディレクトリ、fifo、デバイス、ソケットではありません...)シンボリックリンクを確認した後。

then
    echo "File '${file}' found in $(pwd) path and created on $(date +%D)."

$(pwd)今回は、最新形式のコマンド置換を使用して$PWDPOSIXシェルに作成することが可能です。date +%D現在の日付を印刷します。$fileGNUを想定して最後の修正時刻を印刷するには、dateこのオプションを使用できます-r%D提供された日付形式はmm/dd/yy非常にあいまいで、時間や時間帯の情報を提供しません。$(date -r "$file" +%FT%T%z || echo UNKNOWN)

また、echo任意のデータには使用できません。代わりに使用してくださいprintf '%s\n' "..."

    if [ $(find $file -mmin -5 -type f) ="true" ];

$file今回もsumの出力にSplit + globを使用してくださいfind。また、空白がないため、=コマンドに比較演算子引数が[表示されず、=代わりに偽の=true引数が表示されます。

また、find見つかったファイルパスを印刷するので、次の場合にのみ印刷します(true後続の改行文字はコマンド置換によって削除されるため、複数の改行文字も機能しますが、時々ファイルの1行を読むと、これは起こりません.任意のファイル名を含めることはできません。$filetruetruefmxfileslistfmxfileslist

findまた、(on、...)で始まるファイル名はブロックを引き起こすことに注意してください。-!(

-type f通常のファイルへのシンボリックリンクの場合はfalseを返しますが、[ -f "$file" ]上記はtrueを返します。-xtype f2つの間の一貫性のために、または -Lシンボリックリンクターゲットの修正時間を確認するためにも特定のGNUが必要なので、date -rGNU find4.9以降を想定します。

if [ "$(
  printf '%s\0' "$file" | find -L -files0-from - -prune -type f -mmin -5 -printf true)" = true ]
then
  printf '%s\n' "$file is found to be regular after symlink resolution and has been last modified within the last 5 minutes or in the future"
fi

find-files0-from -ここで、NULで区切られたファイルパスは、上記の窒息問題を回避するための引数ではなく、stdin(そこからインポートされ、4.9以上が必要です)に渡されます。

    then
    cp -a $file /tmp/basefmxfiles

--繰り返しますが、分割+グローブは意味がなく、オプションの区切り文字もありません。あらかじめディレクトリがない場合は/tmp/basefmxfilesコピーとして作成されるため、これを防ぐには、ターゲットディレクトリの末尾に$fileaを追加することをお勧めします(またはここではすでにGNUismsを使用しているのでGNUオプションを使用します)。 :/cp-t

cp -a -- "$file" /tmp/basefmxfiles/
cp -at /tmp/basefmxfiles -- "$file"
    ls -lrt | grep /tmp/basefmxfiles

ls -lrt現在の作業ディレクトリ(ここにある必要があります)の内容を一覧表示し、/apps/common/bau/base/それを出力に含める唯一の方法は/tmp/basefmxfiles次の場合です。

lrwxrwxrwx 1 user group 1 May 17 18:11 somelink -> foo/tmp/basefmxfilesbar

シンボリックリンクがあるので、このコマンドで何をしたいのかわかりません。

    else 
    echo "But the file is not modified in last 5 minutes"
    fi
else
echo "$0: File '${file}' not found."

かどうかを確認するelse部分です。[ -f $file ]$file定期的なファイルなので、エラー(stderrに移動する必要があります)は次のようになります。

printf>&2 '%s\n' "$0: File '$file' not found as a regular file."

ここでは、次のコマンドを使用してすべての操作を実行できますfind(やはりGNU find4.9以降であると仮定)。

cd /apps/common/bau/base || exit
tr '\n' '\0' < /tmp/fmxfileslist |
  find -L -files0-from -                                    \
    -prune                                                  \
    -type f                                                 \
    -printf '%p regular and last modified on %TFT%TT%Tz\n'  \
    '('                                                     \
       -mmin -5 -printf '%p regular and mtime > -5min\n' -o \
          -printf '%p regular but older\n'                  \
    ')' -o -printf '%p not a regular files\n'

アクセスできないファイルの場合は、findstderrにエラーメッセージを表示します。

zshまたは代わりに使用できますsh

#! /bin/zsh -
cd /apps/common/bau/base || exit

          files=( ${(f)"$(</tmp/fmxfileslist)"} )
       regulars=( $^files(N-.)                  )
recent_regulars=( $^regulars(N-m-5)             )
 older_regulars=( ${regulars:|recent_regulars}  )
   non_regulars=( ${files:|regulars}            )

     accessible=( $^files(N-^@)                 )
   inaccessible=( ${files:|accessible}          ) 

たとえば、printこれらの配列の内容は列に対して畏敬の念をr感じたり繰り返されます(zshには引用符なしパラメータを拡張するための分割+グローブがないため、引用符で囲まれていません)。1 Cprint -rC1 -- $arrayfor file ($array) something with $file

シンボリックリンクの確認の前後にファイルの最終変更時刻を取得するには、stat組み込み機能を使用できます。

zmodload zsh/stat
stat -F %FT%T%z -H after -- $file &&
  stat -LF %FT%T%z -H before -- $file &&
  print -r "mtime before symlink resolution: $before[mtime]; after: $after[mtime]"

¹BSDでは、この構文を代わりに使用できますfind -f "$file" ...

おすすめ記事