Shell

用於 ls 輸出的 Foreach 循環

  • April 26, 2015

我正在嘗試使用 foreach 循環處理目錄中的一些文件以獲取 ls 輸出:

IFS=$'\n'
for i in $(ls -1Atu); do
   echo "$i"
done

第一次我認為它有效,但是當我創建名稱為*or的文件時filename*,shell 添加了額外的迭代,因為*解釋為野生字元。

但是,如果我像 ls 一樣轉義輸出for i in "$(ls -1Atu)";,我將獲得一次迭代,並且 $i 將完全包含來自 ls 的輸出。

我們如何解決這個問題?我應該注意ls -1Atu,根據我的需要,任何更可取的變體都會按 atime 對結果文件進行排序。謝謝

背景閱讀:為什麼我的 shell 腳本會因空格或其他特殊字元而窒息?,為什麼你不應該解析 ls 的輸出

設置IFS為換行符意味著在擴展命令替換期間,只有換行符,而不是空格和製表符,將被視為分隔符。您的方法不支持包含換行符的文件名;這是ls¹ 的基本限制。

此外,這就是您遇到的問題,設置IFS對命令替換擴展中發生的其他事情沒有影響,即萬用字元(萬用字元匹配)。您可以關閉萬用字元,然後只要文件名不包含換行符,您的腳本就可以工作。

IFS='
'
set -- *"$IFS"*
if [ -e "$1" ]; then
 echo >&2 "There are file names with newlines. I cannot cope with this."
 exit 2
fi
set -f
for i in $(ls -1Atu); do
   printf '%s\n' "$i"
done
set +f
unset IFS

按日期列舉文件的簡單、可靠的方法是使用純 Bourne 樣式的 shell 以外的東西,例如 zsh,它具有glob 限定符來修改萬用字元匹配的排序方式。

#!/bin/zsh
files_by_access_time=(*(Doa))

¹您可以通過一些實現來解決它ls,但如果您需要可移植性,則不能。

引用自:https://unix.stackexchange.com/questions/198037