我想转移veryverylongfilename.txt
到一个短文件系统NAME_MAX。
mv veryverylongfilename.txt /mnt/tiny
给我一个埃纳图隆- 类型错误:
mv: cannot stat '/mnt/tiny/veryverylongfilename.txt': File name too long
如果需要的话,我应该使用什么命令来截断文件名?
如果该命令可以保留扩展名,那就太好了。此外,最好避免覆盖现有文件,例如在移动veryverylongfilename1.txt
then 时veryverylongfilename2.txt
,通过使用任何类型的唯一标识符代替扩展名之前的最后几个字符。
答案1
以下函数(在 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
.