将文件名缩短为 n 个字符,同时保留文件扩展名

Shorten filename to n characters while preserving file extension

我想在保留扩展名的同时缩短文件名。

我认为 cut 可能是最好用的工具,但我不确定如何保留文件扩展名。

例如,我正在尝试将 abcdefghijklmnop.txt 重命名为 abcde.txt

我想简单地删除文件名的末尾,以便总字符长度不超过 [在本例中] 5 个字符。

我不关心文件名冲突,因为我的数据集可能不包含任何冲突,无论如何我会在重命名任何内容之前进行查找、分析文件和测试。


这样做的背景最终是我想批量截断超过 135 个字符的文件名,以便我可以将文件 rsync 到 Synology NAS 上的加密共享。

我找到了一个搜索所有超过 135 个字符的文件名的好方法: find . -type f | awk -F'/' 'length($NF)>135{print [=13=]}'

我想将其通过管道传输到一个简单的剪切命令,以 trim 将文件名缩小到一定大小。也许有比这更好的方法。我找到了 shorten filenames while preserving extensions 的方法,但我需要遍历所有子目录。

任何帮助将不胜感激,谢谢!

更新说明:

我想使用语法如下的单行代码:

find . -type f | awk -F'/' 'length($NF)>135{print [=14=]}' | some_code_here_to_shorten_the_filename_while_preserving_the_extension

更新

由于您的文件分布在目录树中,您可以使用我原来的方法,但将脚本传递给 sh 命令传递给 find-exec 选项:

n=5 find . -type f -exec sh -c 'f={}; d=${f%/*}; b=${f##*/}; e=${b##*.}; b=${b%.*}; mv -- "$f" "$d/${b:0:n}.$e"' \;

原回答

如果文件名在变量 x 中,则 ${x:0:5}.${x##*.} 应该可以完成工作。

所以你可以这样做

n=5 # or 135, or whatever you like
for f in *; do
  mv -- "$f" "${f:0:n}.${f##*.}"
done

显然,这假设缩短的名称之间没有冲突。如果有冲突,那么only one would survive!所以要小心。

使用 GNU 查找和 bash:

export n=10 # change according to your needs
find . -type f                      \
     ! -name '.*'                   \
       -regextype egrep             \
     ! -regex '.*\.[^/.]{'"$n"',}'  \
       -regex '.*[^/]{'$((n+1))',}' \
       -execdir bash -c '
    echo "PWD=$PWD"
    for f in "${@#./}"; do
        ext=${f#"${f%.*}"}
        echo mv -- "$f" "${f:0:n-${#ext}}${ext}"
    done' bash {} +

这将执行一个 dry-运行,即它显示文件夹后跟要在其中执行的命令。一旦你对它的输出感到满意,你可以在 mv 之前删除 echo (如果你愿意,也可以在 echo "PWD=$PWD" 行)并且它实际上会重命名所有名称超过 [=14 的文件=] 个字符到 n 个字符长度的名称,包括扩展名。

请注意,这不包括隐藏文件和扩展名等于或长于 n 的文件(例如 .hiddenapp.properties,其中 n=10)。

使用bash 字符串操作
详情:https://www.linuxtopia.org/online_books/advanced_bash_scripting_guide/string-manipulation.html.
滚动到 "Substring Extraction"

下面的示例将文件名剪切为 10 个字符并保留扩展名

~ % cat test   

rawFileName=$(basename "")
filename="${rawFileName%.*}"
ext="${rawFileName##*.}"

if [[ ${#filename} < 9 ]]; then
    echo ${filename:0:10}.${ext}
else
    echo 
fi

并测试:

~ % ./test 12345678901234567890.txt
1234567890.txt
~ % ./test 1234567.txt             
1234567.txt