
csh
在我的 SunOS 系統上,我嘗試使用、ls
並尋找晚上 7 點之後建立的所有檔案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
?
注意: SunOS 上-newermt
不支援該選項find
,因此我嘗試使用上面的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
包含換行符,上述內容將無法正常工作。在 csh 中替換"$Source_files"
為$Source_files:q
會更好(但在其他 shell 中不再起作用)。
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
輸出一個用 0 填充的數字,而對於許多ls
實現和許多語言環境(這是 C/POSIX 語言環境中的 POSIX 要求),ls -l
輸出一個用空格填充的數字 (date +%e
)。ls -l
最近日期的輸出Mon dd HH:MM
不是將來的日期,而是Mon dd YYYY
您的方法無法處理的其他日期的輸出。- 如果沒有該
-L
選項,對於符號鏈接,它是符號鏈接的修改時間,而不是它指向的將列出的 zip 檔案的修改時間。perl
或stat()
與目標的實時時間一起使用zsh
。age
- 對於您的
{print $9}
,除了使用者/群組名稱不包含空格之外,您還假設檔案路徑也不包含空格。 xargs
如果檔案路徑包含反斜線或引號,且不在 C 語言環境中執行它,則對未在語言環境編碼中進行文字編碼的檔案名稱上使用該原始輸出將會失敗。- 如果目錄中沒有未隱藏的 zip 文件,在 csh 中,您將收到錯誤
No match
並且ls
不會運行(這至少比ls
使用字面模式調用的 Bourne 風格行為更好),但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