INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml | head -1 | xargs basename`
Я хотів виконати другу команду ( head -1
), тільки якщо перша команда успішна. Як я вдосконалюю цю команду?
INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml | head -1 | xargs basename`
Я хотів виконати другу команду ( head -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)
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
EDIT: переглянувши питання, я зрозумів, що ls
команда, про яку йдеться, шукає найдавніший файл у каталозі. цю ж функцію можна було б перейменовувати oldest
і [[ $file -ot $oldest ]] && oldest=$file
замість цього досягти того ж ефекту. вибачення за будь-яку плутанину.
Важливо зазначити, що ви абсолютно ні за яких обставин у людстві не повинні розбирати вихід лс. ніколи.
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
не підведе.