Filenames
將文件移動到具有較短 NAME_MAX 的文件系統時,必要時截斷
我想移動
veryverylongfilename.txt
到一個短NAME_MAX的文件系統。
mv veryverylongfilename.txt /mnt/tiny
給了我一個ENAMETOOLONG類型的錯誤:mv: cannot stat '/mnt/tiny/veryverylongfilename.txt': File name too long
如果需要,我應該使用什麼命令來截斷文件名?
如果命令可以保留副檔名,那就太好了。此外,最好避免覆蓋現有文件,例如在移動
veryverylongfilename1.txt
then時veryverylongfilename2.txt
,通過使用任何類型的唯一標識符代替副檔名之前的最後幾個字元。
以下函式(在 bash 中測試)將嘗試將其第一個參數移動到其第二個參數。它期望(並測試)第一個參數是文件,第二個參數是目錄。
本地“namemax”變數應調整為文件系統的
NAME_MAX
.moveshort() { local namemax=8 # simple sanity checks [ "$#" -eq 2 ] || return 1 local src=$1 [ -e "$src" ] || return 2 local dest=$2 [ -d "$dest" ] || return 3 local extension=${src##*.} local basename=${src%.*} # the base name has ($namemax - $extension - 1) # characters available to it (1 for the period) local maxbase=$((namemax - ${#extension} - 1)) # shorten the name, if necessary basename=${basename:0:maxbase} # echo "Shortened name: ${basename}.${extension}" # find a new name, if necessary if [ -e "${dest}/${basename}.${extension}" ] then local index=1 local lenindex=${#index} #local newbase=${basename:0:-lenindex} local newbase=${basename:0:maxbase - lenindex} # loop as long as a conflicting filename exists and # we're not out of space in the filename for the index while [ -e "${dest}/${newbase}${index}.${extension}" -a "${#index}" -lt "$maxbase" ] do index=$((index + 1)) lenindex=${#index} newbase=${newbase:0:maxbase - lenindex} done if [ -e "${dest}/${newbase}${index}.${extension}" ] then echo "Failed to find a non-colliding new name for $src in $dest" >&2 return 4 fi basename=${newbase}${index} # echo "new name = ${basename}.${extension}" fi # perform the move mv -- "$src" "${dest}/${basename}.${extension}" }
在完整性檢查之後,該函式會保存副檔名和剩餘的基本文件名,然後確定基本文件名可以使用多少個字元。
如果給定的文件名已經太長,那麼我們就去掉多餘的字元。
如果目標中已經存在縮短的名稱,那麼我們開始循環,從 1 開始,生成一個新的基本文件名,直到我們用完基本文件名中的空間或找到一個不存在的文件。隨著索引的增長,新的基本文件名會被索引壓縮。
如果我們在文件名中用完了空間,該函式會回顯錯誤並返回;否則,它會嘗試執行
mv
.