Передайте вывод по каналу команды, если это успешно

Большинство версий mail (существуют несколько), не поддерживают формат Maildir, только более старый формат Почтового ящика. Используйте более сложный почтовый клиент, такой как Дурак.

13
24.07.2013, 01:47
4 ответа

Попробуйте это:

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 содержит пробелы.

При использовании современной оболочки, такой как удар необходимо использовать a $( ) получите оболочку вместо обратных галочек. Необходимо также рассмотреть изменение стиля переменных. Необходимо обычно избегать использования все-прописных имен переменной в сценариях. Тот стиль обычно резервируется для зарезервированных и переменных окружения.

input_file=$(ls -rt "$my_dir"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename)
8
27.01.2020, 19:53
  • 1
    Не этот b0rk, при отсутствии файлов? –  Mel Boyce 23.07.2013, 16:44
  • 2
    На самом деле: ls -rt GLOB 2>/dev/null | head -n1 | xargs -r basename работы. –  Mel Boyce 23.07.2013, 16:48
  • 3
    @MelBoyce: я добавил это к своему ответу.Спасибо. –   23.07.2013, 16:51
  • 4
    ls является инструментом для того, чтобы в интерактивном режиме посмотреть на информацию о файле. Его вывод отформатирован для людей и вызовет ошибки в сценариях. Используйте шарики или найдите вместо этого. Поймите почему: mywiki.wooledge.org/ParsingLs –  cinelli 23.07.2013, 18:56
  • 5
    @cinelli: Это верно. Я просто отвечал на вопрос. –   23.07.2013, 19:09

В трубопроводе все команды запускаются и выполняются одновременно, не один за другим. Таким образом, необходимо сохранить вывод где-нибудь.

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
9
27.01.2020, 19:53

Найдите последний измененный файл в каталоге:

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
27.01.2020, 19:53
  • 1
    Отметьте это вопреки ls- основанные подходы, если существуют символьные ссылки, время изменения цели символьных ссылок, рассмотрят (добавьте -L опция к ls получить то же поведение там). –  Stéphane Chazelas 07.06.2016, 08:29

Я думаю, что наилучший вариант здесь:

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.

0
27.01.2020, 19:53
  • 1
    Вместо сравнения $? против 0, можно сделать это: if ls -rf $MY_DIR/FILE.*.xml ; then. –   23.07.2013, 16:27
  • 2
    Кроме того, можно перенаправить вывод первой команды к /dev/null. ls -rf $MY_DIR/FILE.*.xml &> /dev/null. Тем путем пользователь не будет видеть дополнительного вывода. –   23.07.2013, 16:36

Теги

Похожие вопросы