Bash 查找文件夹中不包含空格的所有文件

Bash 查找文件夹中不包含空格的所有文件,bash,grep,Bash,Grep,我正试图编写一个bash脚本来查找目录中不包含空格的所有文件,但我发现了一些困难。我正在使用find和grep的组合,它似乎适用于除空格之外的所有内容。我尝试了两种方法: find $d -name '*.js' | xargs grep -L '[ \t]*' 及 两者都不起作用。如何正确匹配空格 编辑:为了澄清,我想在文件内部进行搜索,而不是在文件名中进行搜索。您可以使用grep简单地排除结果(-v,--invert match select non-match line),其中包括查找结

我正试图编写一个bash脚本来查找目录中不包含空格的所有文件,但我发现了一些困难。我正在使用find和grep的组合,它似乎适用于除空格之外的所有内容。我尝试了两种方法:

find $d -name '*.js' | xargs grep -L '[ \t]*'

两者都不起作用。如何正确匹配空格


编辑:为了澄清,我想在文件内部进行搜索,而不是在文件名中进行搜索。

您可以使用
grep
简单地排除结果(
-v,--invert match select non-match line
),其中包括
查找
结果中的空格……类似于:

查找无空白文件名的解决方案

find $d -name '*.js' | grep -v " "
看起来效果不错

根据您的编辑,以下解决方案应适用于您,结果仅为不包含空白内容的文件:

查找内容不包含空格的文件的解决方案(此解决方案中文件名可以包含空格)。

如果您只想返回不包含空格的文件名以及不包含空格的文件内容,我认为这两种方法的结合是可行的:

find $d -name '*.js' |grep -iRlv " " | grep -v " "
当grep找到带有空格的文件时,它返回“success”。如果
-exec
中的命令成功,
find
允许下一个谓词操作;但是,如果下一个运算符是“OR”的
-o
,则
find
仅在
-exec
中的命令不成功时才允许下一个谓词操作。这就是上面的工作原理:它匹配有空格的文件,但只打印出名称不匹配的文件。(括号是必需的,以便
-type f
不受“or”的约束,否则我们会得到所有非文件的内容,如目录名)。如果愿意,可以将其限制为*.js文件:

find . -type f -name '*.js' \
    \( -exec grep -q '[[:space:]]' {} \; -o -print \)
值得注意的是,
grep
不是检测换行符的好工具。为此,你可以考虑一些蛮力:

for file in "$d"/*.js; do
    origcheck=$(md5sum < "$file")
    nospacecheck=$(tr -d '[:space:]' < "$file" | md5sum)
    [[ "$origcheck" = "$nospacecheck" ]] || printf '%s\n' "$file"
done
但是不要提及
-L
,因此不能保证它在其他实现中会以这种方式运行。以下是一些实验:

快速健康检查:

$ grep -L '[a]' <<< 'a'
$ grep -L '[a]' <<< 'b'
(standard input)
文字“t”匹配的事实证明反斜杠-t不是grep的制表符。文字反斜杠也是一个匹配项,所以看起来表达式是由grep按面值接受的。我们知道一种表达真实标签的方法:

$ grep -L $'[ \t]' <<< $'\t'
$ grep -L $'[ \t]' <<< 't'
(standard input)
$ grep -L $'[ \t]' <<< '\'
(standard input)
上述输入字符串是否有零个或多个制表符?对他们两个都是。你只想找到一个角色,所以不要把它复杂化

但是
[:space:]
呢? 你可以简单地写

find . -some -predicate -exec some command {} +
如果出于某种原因,您真的想使用xargs(也许您想利用并行化),那么告诉find和xargs文件名将用NUL字符而不是空格分隔:

find . -some -predicate -print0 | xargs -0 some command

您可能想要
[\t]+
作为第一个;每个文件都将包含与
[\t]*
匹配的空字符串。这些字符串如何不起作用?您正在查找不包含空格或文件名的文件吗?我想在files@GianLucaScoccia谢谢你的澄清。为了更好地回答这个问题,我加入了一些编辑。这会查找不包含空格(可能是OP想要的)的文件名,而不是文件。另外,空格的存在(或不存在)可能是在dirname中,而不是在basename中,或者如果路径的一部分包含换行符,这也是不明确的。添加了一个查找文件的解决方案,即使文件名可能包含空格,也需要更多的引号
find“$d”
,而不是
find$d
,或者带有空格或glob表达式的目录名将表现不好。(另外,请参阅问题的评论:OP已澄清,他们关心的是文件内容中的空格,而不是文件名)。好消息是它可以工作,我将其标记为已接受的答案,坏消息是(以我有限的bash技能)我完全不知道它是如何工作的。要不要解释一下?我看不出比OP的原始解决方案有什么改进,也没有试图解释它是如何工作的。@tripleee Good call。已更新。
$ grep -L '[a]' <<< 'a'
$ grep -L '[a]' <<< 'b'
(standard input)
$ grep -L '[ \t]' <<< 'ab c'
$ grep -L '[ \t]' <<< $'ab\tc'
(standard input)
$ grep -L '[ \t]' <<< t
$ grep -L '[ \t]' <<< '\'
$
$ grep -L $'[ \t]' <<< $'\t'
$ grep -L $'[ \t]' <<< 't'
(standard input)
$ grep -L $'[ \t]' <<< '\'
(standard input)
$ grep -L $'[ \t]*' <<< $'\t'
$ grep -L $'[ \t]*' <<< t
$
$ grep -L '[[:space:]]' <<< ' '
$ grep -L '[[:space:]]' <<< $'\t'
$ grep -L '[[:space:]]' <<< x
(standard input)
find . -some -predicate | xargs some command
find . -some -predicate -exec some command {} +
find . -some -predicate -print0 | xargs -0 some command