回答:
これを試して:
INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml | head -1 | xargs -r basename`
フラグを渡すとxargs
、標準入力()から少なくとも1つの項目を読み取る場合-r
にのみ実行さbasename
れhead -1
ます。
head -1
実行されますが、出力は表示またはキャプチャされません。
また、からのエラー出力をユーザーに見せたくない場合はls
、ls
のstderrストリームをにリダイレクトできます/dev/null
。
INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename`
周りに引用符を追加したことにも注意してください$MY_DIR
。そうすれば$MY_DIR
、スペースが含まれていてもコマンドは失敗しません。
bashなどの最新のシェルを使用している場合は$( )
、バックティックの代わりにキャプチャシェルを使用する必要があります。変数のスタイルを変更することも検討する必要があります。通常、スクリプトではすべて大文字の変数名を使用しないでください。このスタイルは通常、予約済み変数および環境変数用に予約されています。
input_file=$(ls -rt "$my_dir"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename)
ls -rt GLOB 2>/dev/null | head -n1 | xargs -r basename
動作します。
パイプラインでは、すべてのコマンドが次々にではなく、同時に開始および実行されます。そのため、出力をどこかに保存する必要があります。
if ls_output=$(ls -rtd -- "$MY_DIR"/FILE.*.xml); then
first_file=$(printf '%s\n' "$ls_output" | head -n 1)
first_file_name=$(basename -- "$first_file")
fi
ファイル名に改行文字が含まれていないことを前提としていることに注意してください。使用xargs
すると、空白文字、一重引用符、二重引用符、およびバックスラッシュに関する問題も意味します。変数を引用符で囲まないでおくと、スペース、タブ、ワイルドカード文字の問題が発生します。忘れる--
と、ファイル名がで始まる問題が発生します-
。
zsh
文字に関するこれらの制限なしで最も古いファイルのベース名を取得するには(コマンドへの引数のサイズが制限されるという問題も回避します):
first_file_name=($MY_DIR/FILE.*.xml(Om[1]:t))
一致するものがない場合、そのコマンドは失敗し、スクリプトが中止されます。次のこともできます。
first_file_name=($MY_DIR/FILE.*.xml(NOm[1]:t))
この場合、first_file_name
一致する場合は配列に1つの要素が含まれ、一致しない場合は0が含まれます。その後、次のことができます。
if (($#first_file_name)); then
printf 'Match: %s\n' $first_file_name
else
echo >&2 No match
fi
ディレクトリで最新の変更されたファイルを検索します。
latest() {
local file path=${1:-.} ext=${2-} latest
for file in "${path%/}"/*"$ext"; do
[[ $file -nt $latest ]] && latest=$file
done
[[ $latest ]] && printf '%s\n' "$latest"
}
使用法: latest [directory/path/ [.extension]]
を呼び出す代わりにbasename
、パラメータ展開を使用します。
in_file=$(latest in/my/dir .xml)
base_fn=${in_file##*/} base_fn=${base_fn%.*}
これらのコンテンツを含むディレクトリ内:
foo.xml bar.xml baz.xml newest.xml
base_fn変数の内容は次のとおりです。 newest
これを適切に使用してリクエストの目的を果たすには:
check_dir=/path/to/check
check_ext=.xml
if in_file=$(latest "$check_dir" "$check_ext"); then
base_fn=${in_file##*/} base_fn=${base_fn%.*}
else
printf '%s\n' "No file found in $check_dir" >&2
fi
編集:質問を検討すると、問題のls
コマンドはディレクトリ内の最も古いファイルを探していることに気付きました。この同じ関数の名前を変更しoldest
、[[ $file -ot $oldest ]] && oldest=$file
代わりに同じ効果を達成する必要があります。混乱をおaびします。
注意すべき重要なことは、人類のいかなる状況においても、絶対にlsの出力を解析すべきではないということです。決して。
ls
ベースのアプローチとは反対に、シンボリックリンクがある場合、シンボリックリンクのターゲットの変更時間が考慮されることに注意してください(同じ動作を行う-L
オプションを追加しますls
)。
ここでの最良の選択肢は次のとおりだと思います。
ls -rf $MY_DIR/FILE.*.xml
if [ $? -eq 0 ]; then
INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml|head -1|xargs basename `
else
echo "Error!"
fi
ファイルがない場合、lsの戻りコードは2ですが、ファイルが見つかった場合は0になります。
ls
失敗しません。