将文件名缩短为 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
的文件(例如 .hidden
、app.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
我想在保留扩展名的同时缩短文件名。
我认为 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
的文件(例如 .hidden
、app.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