
INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml | head -1 | xargs basename`
head -1
最初のコマンドが成功した場合にのみ、2 番目のコマンド ( ) を実行したいと考えていました。このコマンドを改善するにはどうすればよいですか?
答え1
これを試して:
INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml | head -1 | xargs -r basename`
xargs
フラグを渡すと、標準入力 ( ) から少なくとも 1 つの項目を読み取る場合に-r
のみ実行されます。basename
head -1
head -1
実行されますが、出力は表示またはキャプチャされません。
また、 からのエラー出力をユーザーに表示したくない場合は、の stderr ストリームを にls
リダイレクトできます。ls
/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)
答え2
パイプラインでは、すべてのコマンドが順番にではなく同時に開始され、実行されます。そのため、出力をどこかに保存する必要があります。
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
答え3
ディレクトリ内の最新の変更されたファイルを検索します。
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
代わりに を使用することで、同じ効果を得ることができます。混乱をおかけして申し訳ございません。
注目すべき重要な点は、人類はいかなる状況においても絶対に ls の出力を解析してはならないということです。絶対に。
答え4
ここでの最善の選択肢は次の通りだと思います:
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 になります。