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)
今回は、最新形式のコマンド置換を使用して$PWD
POSIXシェルに作成することが可能です。date +%D
現在の日付を印刷します。$file
GNUを想定して最後の修正時刻を印刷するには、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行を読むと、これは起こりません.任意のファイル名を含めることはできません。$file
true
true
fmxfileslist
fmxfileslist
find
また、(on、...)で始まるファイル名はブロックを引き起こすことに注意してください。-
!
(
-type f
通常のファイルへのシンボリックリンクの場合はfalseを返しますが、[ -f "$file" ]
上記はtrueを返します。-xtype f
2つの間の一貫性のために、または -L
シンボリックリンクターゲットの修正時間を確認するためにも特定のGNUが必要なので、date -r
GNU find
4.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
コピーとして作成されるため、これを防ぐには、ターゲットディレクトリの末尾に$file
aを追加することをお勧めします(またはここではすでに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 find
4.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'
アクセスできないファイルの場合は、find
stderrにエラーメッセージを表示します。
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
C
print -rC1 -- $array
for 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" ...
。