Bash 和带空格的文件名 [英] Bash and filenames with spaces

查看:43
本文介绍了Bash 和带空格的文件名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是一个简单的 Bash 命令行:

The following is a simple Bash command line:

grep -li 'regex' "filename with spaces" "filename"

没问题.以下也可以正常工作:

No problems. Also the following works just fine:

grep -li 'regex' $(<listOfFiles.txt)

其中 listOfFiles.txt 包含要搜索的文件名列表,一个每行文件名.

where listOfFiles.txt contains a list of filenames to be grepped, one filename per line.

listOfFiles.txt 包含文件名时会出现问题嵌入空间.在我尝试过的所有情况下(见下文),Bash 将空格处的文件名,例如 listOfFiles.txt 中的一行包含类似 ./this is a file.xml 的名称,最终尝试运行grep 在每个部分(./thisisafile.xml).

The problem occurs when listOfFiles.txt contains filenames with embedded spaces. In all cases I've tried (see below), Bash splits the filenames at the spaces so, for example, a line in listOfFiles.txt containing a name like ./this is a file.xml ends up trying to run grep on each piece (./this, is, a and file.xml).

我以为我是一个比较高级的 Bash 用户,但是我找不到简单的魔法咒语来让它发挥作用.这是我的东西试过了.

I thought I was a relatively advanced Bash user, but I cannot find a simple magic incantation to get this to work. Here are the things I've tried.

grep -li 'regex' `cat listOfFiles.txt`

如上所述失败(我真的没想到这会奏效),所以我以为我会在每个文件名周围加上引号:

Fails as described above (I didn't really expect this to work), so I thought I'd put quotes around each filename:

grep -li 'regex' `sed -e 's/.*/"&"/' listOfFiles.txt`

Bash 将引号解释为文件名的一部分并给出没有这样的文件或目录"的每个文件(并且仍然将文件名与空格)

Bash interprets the quotes as part of the filename and gives "No such file or directory" for each file (and still splits the filenames with blanks)

for i in $(<listOfFiles.txt); do grep -li 'regex' "$i"; done

这与最初的尝试一样失败(也就是说,它的行为就像引号被忽略)并且非常慢,因为它必须启动一个grep"处理每个文件,而不是一次调用处理所有文件.

This fails as for the original attempt (that is, it behaves as if the quotes are ignored) and is very slow since it has to launch one 'grep' process per file instead of processing all files in one invocation.

以下工作,但需要一些仔细的双重转义,如果正则表达式包含 shell 元字符:

The following works, but requires some careful double-escaping if the regular expression contains shell metacharacters:

eval grep -li 'regex' `sed -e 's/.*/"&"/' listOfFiles.txt`

这是构建命令行的唯一方法吗?正确处理带空格的文件名?

Is this the only way to construct the command line so it will correctly handle filenames with spaces?

推荐答案

试试这个:

(IFS=$'
'; grep -li 'regex' $(<listOfFiles.txt))

IFS 是内部字段分隔符.将它设置为 $' ' 告诉 Bash 使用换行符来分隔文件名.它的默认值是 $' ' 并且可以使用 cat -etv <<<"$IFS" 打印.

IFS is the Internal Field Separator. Setting it to $' ' tells Bash to use the newline character to delimit filenames. Its default value is $' ' and can be printed using cat -etv <<<"$IFS".

将脚本括在括号中会启动一个子shell,以便只有括号内的命令会受到自定义IFS 值的影响.

Enclosing the script in parenthesis starts a subshell so that only commands within the parenthesis are affected by the custom IFS value.

这篇关于Bash 和带空格的文件名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆