AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / ubuntu / 问题 / 521192
Accepted
Paddy Landau
Paddy Landau
Asked: 2014-09-08 08:12:54 +0800 CST2014-09-08 08:12:54 +0800 CST 2014-09-08 08:12:54 +0800 CST

如何通过脚本中的变量将“*”通配符传递给 find 命令的路径参数?

  • 772

我想用来find在一组受通配符限制的文件夹中查找文件,但路径名中有空格。

从命令行,这很容易。以下示例均有效。

find  te*/my\ files/more   -print
find  te*/'my files'/more  -print
find  te*/my' 'files/more  -print

这些将在例如terminal/my files/more和中找到文件tepid/my files/more。

但是,我需要将其作为脚本的一部分;我需要的是这样的:

SEARCH='te*/my\ files/more'
find ${SEARCH} -print

不幸的是,无论我做什么,我似乎都无法find在脚本中的命令中混合使用通配符和空格。上面的示例返回以下错误(请注意反斜杠意外加倍):

find: ‘te*/my\\’: No such file or directory
find: ‘files/more’: No such file or directory

尝试使用引号也会失败。

SEARCH="te*/'my files'/more"
find ${SEARCH} -print

这将返回以下错误,忽略了引号的含义:

find: ‘te*/'my’: No such file or directory
find: ‘files'/more’: No such file or directory

再举一个例子。

SEARCH='te*/my files/more'
find ${SEARCH} -print

正如预期的那样:

find: ‘te*/my’: No such file or directory
find: ‘files/more’: No such file or directory

我尝试过的每个变体都会返回错误。

我有一个解决方法,它有潜在的危险,因为它会返回太多文件夹。我将所有空格转换为问号(单字符通配符),如下所示:

SEARCH='te*/my files/more'
SEARCH=${SEARCH// /?}       # Convert every space to a question mark.
find ${SEARCH} -print

这相当于:

find te*/my?files/more -print

这不仅会返回正确的文件夹,还会返回terse/myxfiles/more它不应该返回的 .

我怎样才能实现我想要做的事情?谷歌没有帮助我:(

scripts
  • 4 4 个回答
  • 55391 Views

4 个回答

  • Voted
  1. Best Answer
    terdon
    2014-11-22T06:06:06+08:002014-11-22T06:06:06+08:00

    完全相同的命令在脚本中应该可以正常工作:

    #!/usr/bin/env bash
    find  te*/my\ files/ -print
    

    如果你需要把它作为一个变量,它会变得有点复杂:

    #!/usr/bin/env bash
    search='te*/my\ files/'
    eval find "$search" -print
    

    警告:

    这样使用eval是不安全的,如果您的文件名可以包含某些字符,可能会导致执行任意且可能有害的代码。有关详细信息,请参阅bash FAQ 48。

    最好将路径作为参数传递:

    #!/usr/bin/env bash
    find "$@" -name "file*"
    

    另一种方法是完全避免find并使用 bash 的扩展通配特性和通配符:

    #!/usr/bin/env bash
    shopt -s globstar
    for file in te*/my\ files/**; do echo "$file"; done
    

    globstarbash 选项允许您使用递归**匹配:

    globstar
          If set, the pattern ** used in a pathname expansion con‐
          text will match all files and zero or  more  directories
          and  subdirectories.  If the pattern is followed by a /,
          only directories and subdirectories match.
    

    要使其 100% 像查找和包含点文件(隐藏文件)一样运行,请使用

    #!/usr/bin/env bash
    shopt -s globstar
    shopt -s dotglob
    for file in te*/my\ files/**; do echo "$file"; done
    

    您甚至echo可以直接使用它们而无需循环:

    echo te*/my\ files/**
    
    • 11
  2. muru
    2014-11-22T02:30:54+08:002014-11-22T02:30:54+08:00

    数组呢?

    $ tree Desktop/ Documents/
    Desktop/
    └── my folder
        └── more
            └── file
    Documents/
    └── my folder
        ├── folder
        └── more
    
    5 directories, 1 file
    $ SEARCH=(D*/my\ folder)
    $ find "${SEARCH[@]}" 
    Desktop/my folder
    Desktop/my folder/more
    Desktop/my folder/more/file
    Documents/my folder
    Documents/my folder/more
    Documents/my folder/folder
    

    (*)扩展为与通配符匹配的数组。并"${SEARCH[@]}"扩展为数组 ( [@]) 中的所有元素,每个元素都单独引用。

    后来,我意识到 find 本身应该能够做到这一点。就像是:

    find . -path 'D*/my folder/more/'
    
    • 2
  3. daneros
    2022-01-03T05:44:15+08:002022-01-03T05:44:15+08:00

    它现在有点过时但是,如果这可以帮助任何人解决这个问题,使用 RE 的整理符号[[.space.]]而不$SEARCH在 find 命令行参数中引用变量,只要扩展路径名中没有特殊字符代替星号,它就可以工作。

    set -x
    mkdir -p te{flon,nnis,rrine}/my\ files/more
    SEARCH=te*/my[[.space.]]files/more
    find $SEARCH
    

    给出以下结果:

    + mkdir -p 'teflon/my files/more' 'tennis/my files/more' 'terrine/my files/more'
    + SEARCH='te*/my[[.space.]]files/more'
    + find 'teflon/my files/more' 'tennis/my files/more' 'terrine/my files/more'
    teflon/my files/more
    tennis/my files/more
    terrine/my files/more
    

    为防止全局化不需要的字符,可以将星号 ( *) 替换为任何整理元素(字符):

    set -x
    mkdir -p -- te{,-,_}{flon,nnis,rrine}/my\ files/more
    SEARCH=te[[:alnum:][.space.][.hyphen.][.underscore.]]*/my[[.space.]]files/more
    find $SEARCH
    

    给出以下结果:

    + mkdir -p -- 'teflon/my files/more' 'tennis/my files/more' 'terrine/my files/more' \
    'te-flon/my files/more' 'te-nnis/my files/more' 'te-rrine/my files/more' \
    'te_flon/my files/more' 'te_nnis/my files/more' 'te_rrine/my files/more'
    + SEARCH='te[[:alnum:][.space.][.hyphen.][.underscore.]]*/my[[.space.]]files/more'
    + find 'te-flon/my files/more' 'te_flon/my files/more' 'teflon/my files/more' \
    'te-nnis/my files/more' 'te_nnis/my files/more' 'tennis/my files/more' \
    'te-rrine/my files/more' 'te_rrine/my files/more' 'terrine/my files/more'
    te-flon/my files/more
    te_flon/my files/more
    teflon/my files/more
    te-nnis/my files/more
    te_nnis/my files/more
    tennis/my files/more
    te-rrine/my files/more
    te_rrine/my files/more
    terrine/my files/more
    

    请注意,要缩短行, [.hyphen.]可以用[.-.]or替换- , 也可以用or[.underscore.]替换。[._.]_



    \为了便于阅读,我自己添加了带有反斜杠 ( ) 的截断行。

    • 1
  4. Paddy Landau
    2014-11-22T06:52:28+08:002014-11-22T06:52:28+08:00

    我终于找到了答案。

    向所有空格添加反斜杠:

    SEARCH='te*/my files/more'
    SEARCH=${SEARCH// /\\ }
    

    此时,SEARCH包含te*/my\ files/more.

    然后,使用eval.

    eval find ${SEARCH} -print
    

    就这么简单!使用绕过来自变量eval的解释。${SEARCH}

    • 0

相关问题

  • 如何在 Nautilus 中管理保存的完整网页及其目录(例如 n.html 和 n_files)

  • 如何每 5 秒运行一次脚本?

  • 如何将必须从其自己的目录中运行的程序添加到面板或主菜单?

  • 如何编写 shell 脚本来安装应用程序列表?

  • Mac OS X Automator 的替代品?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何运行 .sh 脚本?

    • 16 个回答
  • Marko Smith

    如何安装 .tar.gz(或 .tar.bz2)文件?

    • 14 个回答
  • Marko Smith

    如何列出所有已安装的软件包

    • 24 个回答
  • Marko Smith

    无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗?

    • 25 个回答
  • Martin Hope
    Flimm 如何在没有 sudo 的情况下使用 docker? 2014-06-07 00:17:43 +0800 CST
  • Martin Hope
    Ivan 如何列出所有已安装的软件包 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    La Ode Adam Saputra 无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗? 2010-11-30 18:12:48 +0800 CST
  • Martin Hope
    David Barry 如何从命令行确定目录(文件夹)的总大小? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher “以下软件包已被保留:”为什么以及如何解决? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford 如何删除 PPA? 2010-07-30 01:09:42 +0800 CST

热门标签

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve