我有一个无法解决的问题:我需要使用模式重命名大量文件。我尝试使用这,但我总是收到错误。
我有一个文件夹,里面有一个很多文件数。运行后ls -1 | wc -l
,显示其中有 160000 个文件。问题是,我希望将这些文件移动到 Windows 系统,但大多数文件都包含类似:
和 的字符?
,这导致文件在上述基于 Windows 的系统上无法访问。
(作为一个“不解决,而是处理”方法,我尝试在 Windows 系统上启动 LiveCD 并使用实时操作系统移动文件。在 Ubuntu 下,文件在已安装的 NTFS 分区上是可读写的,但当我在 Windows 上重新启动时,它显示该文件在那里,但 Windows 无法以任何方式访问它:重命名、删除或打开。)
我尝试rename 's/\:/_' *
在文件夹内运行,但是参数列表太长错误。一些搜索显示,这是因为我有太多文件,然后我到达这里问题是我不知道如何修改命令以满足我的需求,因为我总是遇到各种错误,例如
- 尝试一下
find -name '*:*' | xargs rename : _
,它给了xargs:不匹配的单引号;默认情况下,引号对 xargs 来说是特殊的,除非您使用 -0 选项 [\n] 第 1 行(eval 1)处的语法错误,靠近“:” [\n] xargs:重命名:以状态 255 退出;中止 - 添加
-0
后将xargs
错误消息变为xargs:参数行太长
这些文件是由各种 PHP 脚本生成的存档文件。最好的解决方案是重命名它们前它们被移到了 Windows,但如果没有办法,我们也许有办法重命名这些文件尽管它们被移动到 Windows。我使用samba
和proftpd
来移动文件。
不幸的是,图形软件是不可能的,因为包含文件的服务器就是服务器,只有命令行界面。
答案1
使用 find 的 -exec 应该可以工作,尽管它会递归遍历子目录,而如果任何子目录恰好包含:
或 ,它就会失败?
。
find . -name "*[:?]*" -exec rename 'y/:?/__/' {} +
您收到的错误argument list too long
是因为*
扩展到目录中的所有 160k 个文件,这超出了系统上的最大参数长度。
$ getconf ARG_MAX
2097152
160k 文件名很容易超过 2MiB。您可以通过一次重命名一个文件来解决此问题
for file in ./*[:?]*; do
mv "$file" "${file//[:?]/_}"
done
或者填充一个数组并分块处理它们。块的大小取决于文件名的平均长度和 ARG_MAX 值;或者只需设置一个足够低的值以确保安全,例如 1000:
files=( ./*[:?]* ) n=${#files[@]}
size=1000
for (( i=0; i<n; i+=size )); do
rename 'y/:?/__/' "${files[@]:i:size}"
done
另请参阅Bash常见问题 30。
答案2
我使用它进行批量重命名:vidir
。它使用的语法与我们大致相同vi
!
apt-get install moreutils
进入包含 160k 个文件的目录
cd dir
启动 vidir
vidir
接下来将文件名中的所有 : 替换为例如 -
: % s/:/-/g
对其他奇怪的字符也做同样的事情,例如?
: % s/?/-/g
现在使用 :w 保存文件
vidir 允许在文本编辑器中编辑目录的内容。