Filenames

將文件移動到具有較短 NAME_MAX 的文件系統時,必要時截斷

  • August 15, 2017

我想移動veryverylongfilename.txt到一個短NAME_MAX的文件系統。

mv veryverylongfilename.txt /mnt/tiny給了我一個ENAMETOOLONG類型的錯誤:

mv: cannot stat '/mnt/tiny/veryverylongfilename.txt': File name too long

如果需要,我應該使用什麼命令來截斷文件名?

如果命令可以保留副檔名,那就太好了。此外,最好避免覆蓋現有文件,例如在移動veryverylongfilename1.txtthen時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.

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