
INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml | head -1 | xargs basename`
Я хотел выполнить вторую команду ( head -1
) только в случае успешного выполнения первой команды. Как мне улучшить эту команду?
решение1
Попробуй это:
INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml | head -1 | xargs -r basename`
Передача xargs
флага -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)
решение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
EDIT: после изучения вопроса я понял, что 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.