没有分词的文件通配?
File globbing without word splitting?
这是一个简化的示例,希望能够说明我的问题。
我有一个脚本需要一个参数作为通配符。有时此通配符包含空格。我需要能够使用通配符进行通配,但分词导致它失败。
例如,考虑以下示例文件:
$ ls -l "/home/me/dir with whitespace"
total 0
-rw-r--r-- 1 me Domain Users 0 Jun 25 16:58 file_a.txt
-rw-r--r-- 1 me Domain Users 0 Jun 25 16:58 file_b.txt
我的脚本 - 简化为使用硬编码模式变量 - 如下所示:
#!/bin/bash
# Here this is hard coded, but normally it would be passed via parameter
# For example: pattern=""
# The whitespace and wildcard can appear anywhere in the pattern
pattern="/home/me/dir with whitespace/file_*.txt"
# First attempt: without quoting
ls -l ${pattern}
# Result: word splitting AND globbing
# ls: cannot access /home/me/dir: No such file or directory
# ls: cannot access with: No such file or directory
# ls: cannot access whitespace/file_*.txt: No such file or directory
####################
# Second attempt: with quoting
ls -l "${pattern}"
# Result: no word splitting, no globbing
# ls: cannot access /home/me/dir with whitespace/file_*.txt: No such file or directory
有没有办法启用 globbing,但禁用分词?
除了手动转义模式中的空格外,我还有其他选择吗?
不要将 glob 保留在引号内以便能够扩展它:
pattern="/home/me/dir with whitespace/file_"
ls -l "${pattern}"*
编辑:
根据已编辑的问题和评论,您可以使用 find
:
find . -path "./$pattern" -print0 | xargs -0 ls -l
我终于明白了!
诀窍是将 internal field separator (IFS
) 修改为空。这可以防止在 IFS
恢复为旧值或取消设置之前对未引用的变量进行分词。
示例:
$ pattern="/home/me/dir with whitespace/file_*.txt"
$ ls -l $pattern
ls: cannot access /home/me/dir: No such file or directory
ls: cannot access with: No such file or directory
ls: cannot access whitespace/file_*.txt: No such file or directory
$ IFS=""
$ ls -l $pattern
-rw-r--r-- 1 me Domain Users 0 Jun 26 09:14 /home/me/dir with whitespace/file_a.txt
-rw-r--r-- 1 me Domain Users 0 Jun 26 09:14 /home/me/dir with whitespace/file_b.txt
$ unset IFS
$ ls -l $pattern
ls: cannot access /home/me/dir: No such file or directory
ls: cannot access with: No such file or directory
ls: cannot access whitespace/file_*.txt: No such file or directory
我发现很难设置和使用 IFS
和 ls
。例如,这不起作用:
$ IFS="" ls -l $pattern
这是因为命令在IFS
变化之前已经进行了分词
这是一个简化的示例,希望能够说明我的问题。
我有一个脚本需要一个参数作为通配符。有时此通配符包含空格。我需要能够使用通配符进行通配,但分词导致它失败。
例如,考虑以下示例文件:
$ ls -l "/home/me/dir with whitespace"
total 0
-rw-r--r-- 1 me Domain Users 0 Jun 25 16:58 file_a.txt
-rw-r--r-- 1 me Domain Users 0 Jun 25 16:58 file_b.txt
我的脚本 - 简化为使用硬编码模式变量 - 如下所示:
#!/bin/bash
# Here this is hard coded, but normally it would be passed via parameter
# For example: pattern=""
# The whitespace and wildcard can appear anywhere in the pattern
pattern="/home/me/dir with whitespace/file_*.txt"
# First attempt: without quoting
ls -l ${pattern}
# Result: word splitting AND globbing
# ls: cannot access /home/me/dir: No such file or directory
# ls: cannot access with: No such file or directory
# ls: cannot access whitespace/file_*.txt: No such file or directory
####################
# Second attempt: with quoting
ls -l "${pattern}"
# Result: no word splitting, no globbing
# ls: cannot access /home/me/dir with whitespace/file_*.txt: No such file or directory
有没有办法启用 globbing,但禁用分词?
除了手动转义模式中的空格外,我还有其他选择吗?
不要将 glob 保留在引号内以便能够扩展它:
pattern="/home/me/dir with whitespace/file_"
ls -l "${pattern}"*
编辑:
根据已编辑的问题和评论,您可以使用 find
:
find . -path "./$pattern" -print0 | xargs -0 ls -l
我终于明白了!
诀窍是将 internal field separator (IFS
) 修改为空。这可以防止在 IFS
恢复为旧值或取消设置之前对未引用的变量进行分词。
示例:
$ pattern="/home/me/dir with whitespace/file_*.txt"
$ ls -l $pattern
ls: cannot access /home/me/dir: No such file or directory
ls: cannot access with: No such file or directory
ls: cannot access whitespace/file_*.txt: No such file or directory
$ IFS=""
$ ls -l $pattern
-rw-r--r-- 1 me Domain Users 0 Jun 26 09:14 /home/me/dir with whitespace/file_a.txt
-rw-r--r-- 1 me Domain Users 0 Jun 26 09:14 /home/me/dir with whitespace/file_b.txt
$ unset IFS
$ ls -l $pattern
ls: cannot access /home/me/dir: No such file or directory
ls: cannot access with: No such file or directory
ls: cannot access whitespace/file_*.txt: No such file or directory
我发现很难设置和使用 IFS
和 ls
。例如,这不起作用:
$ IFS="" ls -l $pattern
这是因为命令在IFS
变化之前已经进行了分词