在Bash中,我想創建一個函數,返回匹配特定模式的最新文件的文件名。例如,我有一個文件目錄:Bash函數來尋找最新的文件匹配模式
Directory/
a1.1_5_1
a1.2_1_4
b2.1_0
b2.2_3_4
b2.3_2_0
我想要以'b2'開頭的最新文件。我如何在bash中做到這一點?我需要在我的~/.bash_profile
腳本中有這個。
在Bash中,我想創建一個函數,返回匹配特定模式的最新文件的文件名。例如,我有一個文件目錄:Bash函數來尋找最新的文件匹配模式
Directory/
a1.1_5_1
a1.2_1_4
b2.1_0
b2.2_3_4
b2.3_2_0
我想要以'b2'開頭的最新文件。我如何在bash中做到這一點?我需要在我的~/.bash_profile
腳本中有這個。
ls
命令有一個參數-t
按時間排序。然後你可以用head -1
抓住第一個(最新)。
ls -t b2* | head -1
但要注意:Why you shouldn't parse the output of ls
我個人的看法是:解析ls
只有危險的時候文件名可以包含一些奇怪的字符,如空格或換行符。如果你可以保證文件名不會包含有趣的字符,那麼解析ls
是相當安全的。
如果你正在開發一個腳本,許多人在很多系統上運行,許多不同的情況下,我非常推薦不要分析ls
。
這裏是如何做到這一點「權利」:How can I find the latest (newest, earliest, oldest) file in a directory?
unset -v latest
for file in "$dir"/*; do
[[ $file -nt $latest ]] && latest=$file
done
對其他人的注意事項:如果您正在爲目錄執行此操作,則需要向ls添加-d選項,例如'ls -td
[解析LS](http://mywiki.wooledge.org/ParsingLs)鏈接表示不這樣做,並建議在[BashFAQ 99](http://mywiki.wooledge.org/BashFAQ/099)。我正在尋找一個1-liner,而不是防彈包含在腳本中,所以我會繼續像@lesmana那樣不安分地解析ls。 – Eponymous 2014-06-05 00:07:37
@同名:如果你正在尋找一個沒有使用脆弱的'ls','printf'%s \ n「b2 * |頭-1'將爲你做。 – 2016-12-01 04:27:02
不尋常的文件名(如含有有效\n
角色可以肆虐用這種分析的一個文件,這裏有一個辦法做到這一點的的Perl:
perl -le '@sorted = map {$_->[0]}
sort {$a->[1] <=> $b->[1]}
map {[$_, -M $_]}
@ARGV;
print $sorted[0]
' b2*
這是一個Schwartzian transform使用有
可能schwartz與你同在! – 2016-06-24 17:45:57
這個答案可能工作,但我不會信任它,因爲糟糕的文檔。 – 2016-12-04 12:56:27
糟糕的文檔?它帶有一個wikipage ... – 2017-04-12 23:20:47
這是可能實現的。需要Bash功能:
# Print the newest file, if any, matching the given pattern
# Example usage:
# newest_matching_file 'b2*'
# WARNING: Files whose names begin with a dot will not be checked
function newest_matching_file
{
# Use ${1-} instead of $1 in case 'nounset' is set
local -r glob_pattern=${1-}
if (($# != 1)) ; then
echo 'usage: newest_matching_file GLOB_PATTERN' >&2
return 1
fi
# To avoid printing garbage if no files match the pattern, set
# 'nullglob' if necessary
local -i need_to_unset_nullglob=0
if [[ ":$BASHOPTS:" != *:nullglob:* ]] ; then
shopt -s nullglob
need_to_unset_nullglob=1
fi
newest_file=
for file in $glob_pattern ; do
[[ -z $newest_file || $file -nt $newest_file ]] \
&& newest_file=$file
done
# To avoid unexpected behaviour elsewhere, unset nullglob if it was
# set by this function
((need_to_unset_nullglob)) && shopt -u nullglob
# Use printf instead of echo in case the file name begins with '-'
[[ -n $newest_file ]] && printf '%s\n' "$newest_file"
return 0
}
它只使用Bash內建函數,並且應該處理名稱中包含換行符或其他不尋常字符的文件。
你可以使用'nullglob_shopt = $(shopt -p nullglob)',然後''nullglob''把'nullglob'放回原來的狀態。 – 2014-11-05 21:14:11
@gniourf_gniourf使用$(shopt -p nullglob)的建議是一個很好的建議。我通常儘量避免使用命令替換('$()'或反引號),因爲它很慢,特別是在Cygwin下,即使命令只使用內置函數。另外,運行命令的子shell上下文有時會導致它們以意想不到的方式運行。我也嘗試避免在變量中存儲命令(比如'nullglob_shopt'),因爲如果你得到的變量值不對,會發生很糟糕的事情。 – pjh 2014-11-06 20:25:55
我很欣賞對細節的關注,如果忽略了這些細節,可能會導致模糊的失敗。謝謝! – 2016-07-31 18:32:07
有一個更有效的方法來實現這一點。請看下面的命令:
find . -cmin 1 -name "b2*"
這個命令在與「B2 *」通配符搜索產生恰好一分鐘前的最新文件。如果你想從最近兩天的文件,那麼你會更好使用以下命令:「」
find . -mtime 2 -name "b2*"
的代表當前目錄。 希望這有助於。
的find
和ls
行之有效的
解決辦法:
find . -name "my-pattern" ... -print |
xargs -0 ls -1 -t |
head -1
讓我們來分析一下:
隨着find
我們可以匹配所有類似的有趣的文件:
find . -name "my-pattern" ...
然後使用-print0
我們可以安全地通過所有的文件名的ls
這樣的:
find . -name "my-pattern" ... -print0 | xargs -0 ls -1 -t
ls -t
將文件排序通過修改時間(最新的第一個)並打印一行。您可以使用-c
按創建時間進行排序。 注意:這將打破包含換行符的文件名。
終於head -1
得到我們排序列表中的第一個文件。
注意:xargs
使用系統限制參數列表的大小。如果這個尺寸超過,xargs
將多次呼叫ls
。這將打破排序,也可能是最終的輸出。運行
xargs --show-limits
檢查系統的限制。
有關更多答案提示,請參閱http://superuser.com/questions/294161/unix-linux-find-and-sort-by-date-modified。排序是獲取最新文件的關鍵步驟 – 2016-12-04 13:06:33