С помощью ls
, хотя вы не всегда сможете получить время, вы должны быть в состоянии получить дату (год, месяц и день месяца).
В локали C вывод даты в ls -l
должен быть либо Mmm dd HH:MM
для недавних файлов (и вы должны быть в состоянии вывести год (либо этот год, либо предыдущий) или Mmm dd YYYY
для старых файлов или файлов с временем модификации в будущем. Таким образом, вы всегда сможете получить дату (YYYY-mm-dd) из этого:
eval "$(date +'year=%Y month=%m')"
LC_ALL=C ls -dn file | awk -v y="$year" -v m="$month" '{
month = index("--JanFebMarAprMayJunJulAugSepOctNovDec", $6) / 3
day = $7
if ($8 ~ /:/)
year = y - (month > m)
else
year = $8
printf "%04d-%02d-%02d\n", year, month, day
exit}'
Теперь, если вам нужно полное время модификации с максимальной точностью, боюсь, что для этого нет стандартной команды.
Вы можете найти некоторые реализации ls
, которые имеют опции для этого (ls --full-time
в GNU ls
или -... D
с FreeBSD ls
, например)
Существует ряд различных и несовместимых реализаций команды stat
(IRIX, zsh
builtin, GNU, BSD), которые могут дать вам это.
Или вы можете использовать -printf
предикат GNU find
. Или опцию -r
GNU date
.
Не все реализации дадут вам субсекундную детализацию. Остерегайтесь часовых поясов и DST, поскольку в зависимости от выбранного формата и часового пояса, в котором вы находитесь, данный вывод может быть неоднозначным и относиться к более чем одной возможной дате.
Для симлинков вы также можете спросить себя, какое время модификации ссылки или ее цели вам нужно. Некоторые из упомянутых здесь опций будут делать то или другое по умолчанию, а некоторым из них можно приказать делать то или другое по требованию.
zsh
stat: stat -F '%Y-%m-%d %T.%N %z' +mtime file
1992-05-13 14:57:00.123368710 +0100
stat
stat -c %y file
1992-05-13 14:57:00.123368710 +0100
stat
: stat -t '%F %T %z' -f %Sm file
1992-05-13 14:57:00 +0100
stat
: stat -m file
find
: find file -prune -printf '%TF %TT %Tz\n'
1992-05-13 14:57:00.1233687100 +0100
date
: date -r file '+%F %T.%N %z'
1992-05-13 14:57:00.123368710 +0100
ls
: ls -D '[%F %T %z]' -l file
-r-xr-xr-x 2 bin bin 372298 [1992-05-13 14:57:00 +0100] file
ls
: ls --full-time -l file
-r-xr-xr-x 2 bin bin 372298 1992-05-13 14:57:00.123368710 +0100 file
ls
: ls -Z '%(mtime:time=%F %T.%N %z)s'
1992-05-13 14:57:00.123368710 +0100
AIX, которую, судя по вашему ls
синопсису, вы используете, имеет команду istat
(AIX 5. 3 man page), которая отображает даты полностью (без субсекундной детализации, и неоднозначно, если вы не заставите TZ
заменить UTC0
), хотя ее не так легко разобрать:
$ LC_ALL=C TZ=UTC0 istat file
Inode 10360 on device 10/6 File
Protection: r-xr-xr-x
Owner: 2(bin) Group: 2(bin)
Link count: 2 Length 372298 bytes
Last updated: Wed May 13 14:08:13 1992
Last modified: Wed May 13 13:57:00 1992
Last accessed: Sun Jan 31 15:49:23 1993
Также обратите внимание, что для симлинков вы получите дату цели симлинка, а не самого симлинка.
Если у вас нет доступа ни к одной из этих программ, лучшим вариантом для переносимости может быть perl
:
$ perl -MPOSIX -le 'print strftime("%Y-%m-%d %T %z", localtime((lstat(shift))[9]))' file
1992-05-13 14:57:00 +0100
Обратите внимание, что немногие системы имеют время создания для файлов (иногда называемое временем рождения), и нет стандартного API, не говоря уже о команде для запроса, так что ситуация еще хуже, чем со временем модификации.
Сложность заключается в том, что если вы замените все '
на "
, а затем все "
на '
, вы останетесь только с '
. Итак, сначала вам нужно заменить '
чем-то другим, например, символом NULL ( \ 0
), которого, как вы можете смело предположить, не будет во входном файле, - затем «
на '
, а затем снова замените это что-то еще на »
. Например, в perl:
$ perl -pe "if(/KEYWORD){s/'/\0/g; s/\"/'/g; s/\0/\"/g}" file
KEYWORD_1 table name column = 'string' AND column = 'string'
Additional text
.
.
.
KEYWORD_2 text "text in quote" etc.
-pe
: p rint каждую строку ввода после применения сценария, заданного -e
. if (/ KEYWORD /) {something}
: выполните something
, только если эта строка соответствует KEYWORD
. s / foo / bar / g
: замените все вхождения foo
в строке на bar
. g
означает «глобальный». Без него будет заменено только первое вхождение в каждой строке. Обратите внимание, что, поскольку сам скрипт заключен в двойные кавычки, двойные кавычки внутри скрипта необходимо экранировать ( \ "
).
Как указано в комментариях, есть более прямой способ В первую очередь мне следовало подумать:
perl -pe "tr/'\"/\"'/ if /^KEYWORD/" file
Оператор tr
транслитерирует списки символов. Общий формат - tr / searchlist / replacementlist /
. Таким образом, он заменит все '
с «
и все »
с '
только в строках, соответствующих KEYWORD
.
Немного грубая, но работающая переменная GNU awk:
$ awk -v sq="'" '/KEYWORD/{if ($0~sq){ gsub(sq,"\"")} else if ($0~"\"") gsub(/\"/,sq)};1' input.txt
KEYWORD_1 table name column = 'string' AND column = 'string'
Additional text
.
.
.
KEYWORD_2 text "text in quote" etc.
sq используется для представления одинарных кавычек, поскольку встраивание ее в сам кодовый блок - это немного неудобно для awk. Основная идея заключается в том, что мы ищем шаблон, если шаблон найден - мы принимаем решение, что заменить. Final 1
просто указывает awk напечатать строки.
Что касается вывода его в файл, просто используйте оператор оболочки >
, чтобы перенаправить текст во временный файл и заменить старый файл новым с помощью команды mv
.
Замена набора символов на другой набор символов обычно является задачей для команды tr
, но поскольку вы хотите сделать это только в определенных строках, это лучше всего сделать с помощью sed
, которая имеет команду y
, аналогичную tr
:
sed -e "/^KEYWORD_1/ y/\"/'/" \
-e "/^KEYWORD_2/ y/'/\"/" \
file
Каждая команда sed
здесь начинается с селектора строки /^KEYWORD/
, который инструктирует sed
работать только со строкой, соответствующей шаблону между /
. Здесь шаблоны начинаются с символа ^
, чтобы указать, что они должны быть найдены в начале строки.
После селектора строк следует команда подстановки sed
y/set1/set2/g
, которая заменяет каждое вхождение символа в set1
на символ, занимающий ту же позицию в set2
.
Теперь, если в одной строке вы хотите заменить каждый "
на '
и одновременно каждый '
на "
, вы можете использовать только одну команду:
sed -e "/^KEYWORD_1\|^KEYWORD_2/ y/\"'/'\"/" file