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
    • 最新
    • 标签
主页 / unix / 问题 / 669630
Accepted
MountainX
MountainX
Asked: 2021-09-19 14:44:12 +0800 CST2021-09-19 14:44:12 +0800 CST 2021-09-19 14:44:12 +0800 CST

对于 path 下的每个目录,从该目录执行 shell 脚本(当 find -execdir 不合适时)

  • 772

我有一个现有的 bash 脚本,我这样称呼它:

find /path/to/my/stuff -type d -exec sh -c 'cd "$0"; /path/to/my/script.sh function_name fn_parameter' {} \;

我经常更改/path/to/my/stuffand fn_parameter。我有时还需要更改function_name.

不断重新输入这个命令变得很乏味,所以我想将它包装在另一个脚本中,并像这样传递这三个参数:

wrapper.sh function_name "/path/to/my/stuff" fn_parameter

旁注:我更改了参数的顺序,因为“function_name”是最不频繁更改的参数。

当我尝试制作这个包装脚本时,我被引用和转义弄得不知所措。我查看了 shellcheck.net 中的脚本,还尝试使用数组 for cmd(请参阅下面的失败尝试之一)但没有成功。我确实理解问题很可能是引号和反斜杠没有得到尊重,但我不明白如何解决这个问题。

这是我许多失败的尝试之一:

包装器.sh

#!/bin/bash
function_name=$1
mpath="$2"
arg=$3

find "$mpath" -type d -exec sh -c "cd \"$0\"; /path/to/my/script.sh $function_name $arg" {} \;

这是失败尝试的另一个示例:

#!/bin/bash
function_name=$1
mpath="$2"
arg=$3
cmd="'cd \$0; /path/to/my/script.sh $function_name $arg'"
echo "find \"$mpath\" -type d -exec sh -c $cmd {} \;"
find "$mpath" -type d -exec sh -c $cmd {} \;

在上面的例子中,如果我在命令行输入 echo 语句的输出,它就可以正常工作。但是包装器失败了:

$0;: -c: line 1: unexpected EOF while looking for matching `''
$0;: -c: line 2: syntax error: unexpected end of file

为了完整起见,myscript.sh 与此类似:

#!/bin/bash

fn1() {
  ...
}

fn2() {
  ...
}


fn3() {
  ...
}

"$@"
bash shell-script
  • 2 2 个回答
  • 127 Views

2 个回答

  • Voted
  1. Best Answer
    Kusalananda
    2021-09-20T00:07:23+08:002021-09-20T00:07:23+08:00

    您的代码的两个变体,每个都将特殊值传递到您从中调用的内联脚本中find:

    #!/bin/sh
    
    mpath=$1
    fn_name=$2
    fn_arg=$3
    
    find "$mpath" -type d -exec sh -c '
        cd "$3" && /path/to/my/script.sh "$1" "$2"' sh "$fn_name" "$fn_arg" {} \;
    

    找到目录时,find 只需将两个变量的值fn_name作为目录路径参数之前的两个第一个参数传递fn_arg到脚本中。sh -c在脚本内部,我们使用前两个参数作为脚本的参数,第三个作为进入的目录路径cd。

    注意$0将包含字符串sh。shell 将在它可能产生的任何错误消息中使用这个(任意)字符串(你在你的问题中展示了一个例子)。该$0值不是位置参数列表的一部分。

    另一个变体,它一次调用具有尽可能多的目录路径的内联脚本:

    #!/bin/sh
    
    mpath=$1
    fn_name=$2
    fn_arg=$3
    
    find "$mpath" -type d -exec sh -c '
        fn=$1 arg=$2; shift 2
        for dirpath do
            ( cd "$dirpath" && /path/to/my/script.sh "$fn" "$arg" )
        done' sh "$fn_name" "$fn_arg" {} +
    

    通过在命令末尾更改\;为,我们使用批量找到的目录路径调用 。然后,内联脚本必须遍历这些并依次调用您的脚本。+findsh -c

    内联脚本首先从位置参数列表中选择函数名称和参数,然后将它们从该列表中移出。然后它循环遍历剩余的参数和调用cd以及每个脚本。以下是插入了一些额外空气的内联脚本:

    fn=$1    # 1st argument from find
    arg=$2   # 2nd argument from find
    shift 2  # remove them from the list
    
    # Iterate over the remaining arguments
    for dirpath do
        ( cd "$dirpath" && /path/to/my/script.sh "$fn" "$arg" )
    done
    

    我在子 shell 中运行循环体,以避免cd每次运行脚本后都必须“返回”。

    我在sh这里使用,而不是bash因为sh运行此代码没有任何不足。此外,find此处显示的命令仅使用标准功能。

    • 4
  2. MountainX
    2021-09-19T16:23:56+08:002021-09-19T16:23:56+08:00

    这是我提出的(和有效的)解决方案:

    #!/bin/bash
    function_name=$1
    mpath="$2"
    marg=$3
    
    while IFS= read -r -d '' sdir
    do
      cd "$sdir"
      /path/to/my/script.sh "$function_name" "$marg"
    done <   <(find "$mpath" -type d -print0)
    

    编辑:针对评论,此解决方案不适用于相对路径。

    • -1

相关问题

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • MySQL Select with function IN () with bash array

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

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

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

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

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve