当我将大量文件和文件夹从 Windows 系统复制到 Linux 系统时遇到了编码问题,现在我可以看到许多文件名称中带有问号。
我想知道有多少文件/文件夹受到影响,所以我尝试
find . -type d -o -type f -name '*\?*'
和
find . -type d -o -type f -name '*?*'
没有运气。
它列出了许多名称中没有问号的文件/文件夹...(请注意,搜索必须是递归的)
你有解决方案吗 ?
(此外,如果您有第二个命令来计算受影响的文件数量,我会很高兴:))
[编辑] 感谢您的回答,但问题似乎实际上是find
由于编码问题,这些文件和文件夹被排除在命令之外。首先,它似乎不是 ? 字符,而是更像 � 之类的东西。我尝试搜索它们名称的其他部分,但它们仍然没有出现(如果我重命名它们,我就可以摆脱编码问题,它们会再次可见find
)。
这帮我列出并统计它们。
谢谢
答案1
您有一个需要解决的编码问题。
显示?
的ls
是一个占位符,并不代表该文件名为?
。
这是重现问题的方法,使用iconv
在通常的 utf8 配置的 Linux 系统上:
$ mkdir /tmp/test
$ cd /tmp/test
$ touch $(echo é | iconv -t windows-1252) # that's the eacute character
$ ls
?
$ ls|cat
�
最后一行只是表示“显示了无效的 utf8 编码”,可能无法正确复制/粘贴而不会丢失其信息。windows-1252
只是一个例子。 可能还有许多其他的(例如iso-8859-1
:)。 信息仍然存在:
$ ls|iconv -f windows-1252
é
因此,一旦您弄清楚在 Linux 上用哪种编码来编写这些文件(尝试iconv -l|egrep -i 'win|iso-8859'
可能的候选列表),您就可以尝试批量重命名。请注意,虽然一个示例可能有效,但它可能会在其他文件上失败。
重命名示例:
ENCODING="windows-1252" # once the right encoding was found
for file in *; do
dest="$(printf '%s' "$file" | iconv -f "$ENCODING")"
mv -i "$file" "$dest.new"
mv -i "$dest.new" "$dest"
done
答案2
find
意思-o
是“或者“,所以您可能遇到了优先级问题……
你指的是哪一个?
-type d
或者(-type f
和-name '*\?*'
)- 所有目录
- 所有文件
?
名称中包含
- (
-type d
或者-type f
)和-name '*\?*'
?
仅限名称中含有 的目录和文件
您可以使用大括号find
,因此您的命令变成:
find . \( -type d -o -type f \) -name '*\?*'
例子:
$ touch 'aaa' 'a?a'
$ mkdir 'bbb' 'b?b'
$ touch 'bbb/ccc' 'bbb/c?c'
$ find . -type d -o -type f -name '*\?*'
.
./bbb
./bbb/c?c
./b?b
./a?a
$ find . \( -type d -o -type f \) -name '*\?*'
./bbb/c?c
./b?b
./a?a
然后,您可以通过管道将输出输入到以下行中wc -l
来计算行数:
$ find . \( -type d -o -type f \) -name '*\?*' | wc -l
3
其他人建议您删除-type d -o -type f
。这是一个不错的选择,除非您尝试排除其他类型(例如:块设备/字符设备/符号链接/管道/套接字)
答案3
您的第一个命令可以修改如下:
find . -type d -name '*\?*' -o -type f -name '*\?*'
这样,过滤器就适用于文件和目录(否则您将列出所有目录和仅过滤文件)。
简单得多,正如建议的那样吉米在评论中,将是:
find . -name '*\?*'
请注意,find
默认在当前目录中搜索,因此.
也可以省略:
find -name '*\?*'
另外,你可以 grep 结果:
find | grep ?
计算相关实体(建议的解决方案是吉米):
find | grep ? | wc -l
命令来计算受影响的文件数量
正如您所问的,只计算文件数量:
find -type f | grep ? | wc -l
测试运行:
?aa
a?a
aa?
aaa
$ find | grep ?
./a?a
./?aa
./aa?
评论:
我认为grep
需要-F
按字面意思处理的选项?
,但看来它无论如何都不会被视为特殊字符,除非-E
使用开关。
-F, --fixed-strings Interpret PATTERN as a list of fixed strings (instead of regular expressions), separated by newlines, any of which is to be matched. -E, --extended-regexp Interpret PATTERN as an extended regular expression (ERE, see below).
问题已更新:
列出名称中带有问号 (�) 的所有文件和文件夹
没有太大变化:find -name '*�*'
要么find | grep �
测试运行:
�aa
a�a
aa�
aaa
$ find -name '*�*'
./a�a
./�aa
./aa�
还有一个问题:
如果要查找包含外来字符的文件或目录,可以通过指定要查找的字符来过滤结果预计. 只需将您喜欢的任何字符添加到列表中不想要强调的是:
find | grep -P '[^\w./-_*]'
这在你不知道这是有问题的字符。请注意,这个问题在 Stackexchange 上已经被问过多次,并且已经得到过回答。