unix bash - 保存环境变量和循环

发布于 2024-12-19 02:38:52 字数 578 浏览 1 评论 0原文

假设您的目录中有一个first.sh 文件:“/home/userbob/scripts/foo/”。基本上我想知道如何循环遍历特定目录,每次都返回到更高级别的目录并重复。

.sh 文件有类似这样的伪代码:

#!/bin/bash
curdi={$PATH} #where the first.sh file sits on the server
FOLDERS="$curdi/waffles/inner/
$curdi/pancakes/inner/
$curdi/bagels/inner/"
for f in $FOLDERS
do
    cd $f
     cp innerofinner/* .
     cd $curdi
done

这个想法是以某种方式将 /home/userbob/scripts/foo/waffles/inner/innerofinner 的所有内容复制到 /home/userbob/scripts/foo/waffles/inner/ (基本上只是重复有煎饼、百吉饼等的路径。)

无法对 /home/userbob/scripts/foo/ 下的所有目录(*)执行此操作,因为有一些我不想复制。

Let's say you have a first.sh file in a directory: "/home/userbob/scripts/foo/". Basically I would like to know how to loop through specific directories, each time going back up to a higher level directory and repeating.

The .sh file has something like this pseudocode:

#!/bin/bash
curdi={$PATH} #where the first.sh file sits on the server
FOLDERS="$curdi/waffles/inner/
$curdi/pancakes/inner/
$curdi/bagels/inner/"
for f in $FOLDERS
do
    cd $f
     cp innerofinner/* .
     cd $curdi
done

The idea is to somehow copy all the contents of /home/userbob/scripts/foo/waffles/inner/innerofinner to /home/userbob/scripts/foo/waffles/inner/
(and basically repeating just with the path having pancakes, bagels.etc.)

Can't do it for all directories (*) under /home/userbob/scripts/foo/ because there are some that I don't want to copy.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

蹲墙角沉默 2024-12-26 02:38:52

这应该可以做到:

for name in waffles pancakes bagels
do
    cp "$curdi/$name/inner/innferofinner/"* "$curdi/waffles/inner"
done

This should do it:

for name in waffles pancakes bagels
do
    cp "$curdi/$name/inner/innferofinner/"* "$curdi/waffles/inner"
done
你曾走过我的故事 2024-12-26 02:38:52

行走文件树?听起来像是find 的工作!

#!/usr/local/bin/env bash

# only environment variables should be all-caps
dirs=({bagels,pancakes}/inner)

find "${dirs[@]}" -type d -maxdepth 1 -mindepth 1 -name innerofinner -execdir bash -c 'cp "$1"/* .' -- {}  \;

我做了一个部分路径并假设工作目录为 /home/userbob/scripts/foo。绝对路径也可以,看起来像这样

dirs=(/home/userbob/scripts/foo/{bagels,pancakes}/inner)

这会找到列出的目录下一层名为“innerofinner”的所有目录,并在其父目录中执行 bash 和一个简单的 cp 脚本。

如果您想知道这是如何工作的,请阅读下文。

dirs=() 语法创建一个名为 dirs 的空数组。 dirs+(ab) 创建一个数组,其中 a 位于索引 0 处,b 位于索引 1 处。任何以空格分隔的字符串都可以在此处使用。在 shell 脚本中,{a,b,c} 扩展为 ab c,但 A{a,b,c}B 扩展为 >AaB AbB AcB。因此,指定 {bagels,pancakes}/inner 只是表示 bagels/innerpancakes/inner 的一种方式,而无需输入太多内容。

bash 中的变量可以用 $foo${foo} 扩展;这些是相同的。 shell 中的数组可以使用 ${foo[@]} 扩展为其所有元素,并用空格分隔(如果您了解 perl 或 php,这将有意义)并引用扩展(始终是shell 中的好主意!)防止变量内部的空格再次被 shell 处理。因此,"${dir[@]}" 变为 bagels/inner pancakes/inner

知道了这一点,我们看到 find 命令已变成 find bagels/inner pancakes/inner -maxdepth 1 -mindepth 1 -type d -name innerofinner 如果执行此命令,它将返回两行:都是完整的每个 innerofinner 目录的路径。我们现在想要的就是为每个人做一些事情,-execdir 做得很好。

Walking file trees? Sounds like a job for find!

#!/usr/local/bin/env bash

# only environment variables should be all-caps
dirs=({bagels,pancakes}/inner)

find "${dirs[@]}" -type d -maxdepth 1 -mindepth 1 -name innerofinner -execdir bash -c 'cp "$1"/* .' -- {}  \;

I did a partial path and assumed a working directory of /home/userbob/scripts/foo. An absolute path would work, too, and would look like

dirs=(/home/userbob/scripts/foo/{bagels,pancakes}/inner)

This finds all directories exactly one level below the listed directory that are named "innerofinner" and, in their parent directories, executs bash and a simple cp script.

If you're wondering how this works, read below.

The dirs=() syntax creates an empty array named dirs. dirs+(a b) creates an array with a at index 0 and b at index 1. Any whitespace-delimited string will work, here. In a shell script {a,b,c} expands to a b c but A{a,b,c}B expands to AaB AbB AcB. So specifying {bagels,pancakes}/inner is just a way to say both bagels/inner and pancakes/inner without having to type as much.

A variable in bash can be expanded with $foo or with ${foo}; these are the same. An array in shell can be expanded to all of its elements with ${foo[@]} delimited by spaces (if you know perl or php this will make some sense) and quoting the expansion (always a good idea in shell!) prevents spaces innside the variable from being processed again by the shell. Thus, "${dir[@]}" becomes bagels/inner pancakes/inner.

Knowing this we see that the find command has become find bagels/inner pancakes/inner -maxdepth 1 -mindepth 1 -type d -name innerofinner and if you execute this it will return exactly two lines: both full paths to each innerofinner directory. All we want now is to do something for each one, which -execdir does nicely.

初见 2024-12-26 02:38:52

使用递归函数或递归调用脚本。

Use a recursive function or invoke the script recursively.

成熟的代价 2024-12-26 02:38:52

我不确定我是否正确理解您的问题陈述。你的伪代码看起来不错。但是,我发现以下行有问题。

curdi={$PWD}

它不会为您提供脚本所在的目录,而是提供您所在的目录。如果您的脚本目录位于路径中并且您从主目录运行脚本,则 $curdi 将指向您的主目录而不是目录你的脚本所在的位置。这将导致不希望的结果。

I am not sure if I understand your problem statement correctly. Your psuedo code seems good. But, I see a problem with the following line.

curdi={$PWD}

It does not give you the directory where the script resides but gives the directory you are in. If your script directory is in the path and you are running the script from your home directory then $curdi would point to your home directory and not the directory where your script resides. This will lead to undesired results.

情深已缘浅 2024-12-26 02:38:52

顺便说一句,如果您确实想按照伪脚本尝试的方式执行此操作,则可以这样做假设

#!/usr/bin/env bash

for f in "$PWD"/{waffles,pancakes,bagels}/inner ; do
    cd "$f"
    cp innerofinner/* .

    # if you know for sure that it's one level up
    cd ..
done

$PWD 对您来说是“当前”目录的足够好的指示符。我,我会把它传递给脚本。

#!/usr/bin/env bash

base="${1-$PWD}"

for f in "$base"/{waffles,pancakes,bagels}/inner ; do
    cd "$f"
    cp innerofinner/* .
    cd ..
done

称其为

breakfast.sh /home/userbob/scripts/foo/

Incidentally, if you really wanted to do it in the way that your pseudo-script attempts it, you'd do it like this

#!/usr/bin/env bash

for f in "$PWD"/{waffles,pancakes,bagels}/inner ; do
    cd "$f"
    cp innerofinner/* .

    # if you know for sure that it's one level up
    cd ..
done

Presuming that $PWD is a good enough indicator of "current" directory for you. Me, I'd pass it in to the script.

#!/usr/bin/env bash

base="${1-$PWD}"

for f in "$base"/{waffles,pancakes,bagels}/inner ; do
    cd "$f"
    cp innerofinner/* .
    cd ..
done

at call it like

breakfast.sh /home/userbob/scripts/foo/
枫林﹌晚霞¤ 2024-12-26 02:38:52
find . \( -iname '*waffles*innferofinner*' -o \
          -iname '*pancakes*innferofinner*' -o \
          -iname '*baggels*innferofinner*' \) \
          -type f \
          -exec cp {} "`echo {} | sed 's:\(.*\)/[^/]\+/[^/]\+:\1:'` \;

应该做。查找所需子目录中的每个文件,然后根据其名称复制它。

华泰

find . \( -iname '*waffles*innferofinner*' -o \
          -iname '*pancakes*innferofinner*' -o \
          -iname '*baggels*innferofinner*' \) \
          -type f \
          -exec cp {} "`echo {} | sed 's:\(.*\)/[^/]\+/[^/]\+:\1:'` \;

Should do. Finds every file in the desired subdirs, then copies it based on its name.

HTH

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文