
В моей системе SunOS я пытаюсь найти все файлы, созданные после 19:00, используя csh
, ls
и awk
.
ls -l "${Source_files_Dir}"/*.zip| awk -v today="$(date "+%b %d")" '{
date=$6" "$7; time=$8; if (date == today && substr(time,1,2) >= 19)
print $9 }'|xargs -n 1 basename
Эта команда работает в , ksh
но не в csh
. Как мне добиться этого в csh
?
Примечание: -newermt
опция не поддерживается в find
SunOS, поэтому я попробовал использовать указанную выше ls
команду.
решение1
В любом случае этот подход довольно ненадежен, лучше использовать perl
:
perl -MPOSIX -MFile::Basename -le '@start = localtime; @start[0..2] = (0,0,19); $start = mktime(@start); for (@ARGV) {print basename$_ if @s = stat$_ and $s[9] >= $start}' -- "$Source_files_Dir"/*.zip
Не уверен, зачем вам использовать csh в этом столетии, но обратите внимание, что вышеприведенное не работает должным образом, csh
если $Source_files_Dir
содержит символы новой строки. Замена "$Source_files"
на $Source_files:q
была бы лучше в csh (но больше не работает в других оболочках).
Solaris (ранее известная как SunOS) также обычно устанавливается zsh
, и для этого достаточно сделать следующее:
autoload age
print -rC1 -- $Source_files_Dir/*.zip(Ne[age 19:00]:t)
Перечислим некоторые проблемы вашего подхода:
ls -l "${Source_files_Dir}"/*.zip
: если$Source_files_Dir
начинается с-
, то он будет рассматриваться как опцияls
. Как правило, вам необходимо--
отметить конец опций, если то, что следует за ними, является переменной.- если какой-либо из zip-файлов имеет тип каталога, то будет перечислено его содержимое. При использовании
ls
с glob или вообще переменными данными, вы обычно хотите использовать опцию-d
:ls -ld -- ...
- В частности, в csh, если
$Source_files_Dir
он содержит символы новой строки, это вызовет синтаксическую ошибку.$Source_files_Dir:q
Лучше в csh, как отмечено выше. - В любом случае вы предполагаете, что пути к файлам (имена файлов и цели символических ссылок, которые
ls -l
также сообщаются) не содержат символов новой строки, поскольку вы обрабатываете вывод наls
основе строк. - Вы предполагаете, что дата/время находятся в полях 6, 7, 8, которые развалятся, если имена пользователей или групп содержат пробелы. Использование
-n
вместо (или в дополнение к)-l
для получения числовых uid/gids сделает его более надежным (и позволит избежать потенциально дорогостоящего перевода в имена). date +%d
выводит число, дополненное нулями, тогда как во многихls
реализациях и во многих локалях (а это требование POSIX в локали C/POSIX)ls -l
выводит число, дополненное пробелами (date +%e
).ls -l
выводит данныеMon dd HH:MM
не для последних дат, аMon dd YYYY
для других дат, которые ваш подход не обрабатывает.- без этой
-L
опции для символических ссылок будет указано время модификации символической ссылки, а не время модификации zip-файла, на который она указывает.perl
'sstat()
илиzsh
'age
работают с mtime цели. - с вашим
{print $9}
, в дополнение к именам пользователей/групп, не содержащим пробелов, вы предполагаете, что пути к файлам также не содержат пробелов. - использование
xargs
этого необработанного вывода завершится ошибкой, если пути к файлам содержат обратные косые черты или кавычки, а также если не запустить его в локали C, то для имен файлов, которые не являются текстом, закодированным в кодировке локали. - Если в каталоге нет нескрытого zip-файла, в csh вы получите ошибку
No match
иls
не запустите его (что, по крайней мере, лучше, чем поведение в стиле Bourne, когдаls
вызывается буквально с шаблоном), но онxargs
все равно будет запущен, иbasename
все равно будет запущен один раз без аргумента, что, вероятно, вызовет запутанную ошибку.
решение2
Я получил ответ для csh, вместо того '$'
чтобы backticks
сохранить сегодняшнюю дату в переменной, today
а не получить ее в awk
.
set today=`date "+%b %d"`
ls -l "$Source_files_Dir"/*.zip | awk -v today="$today" ' \
{ \
date=$6" "$7; \
time=$8; \
if (date == today && substr(time,1,2) >= 19) print $9; \
}'|xargs -n 1 basename