将多个文件中的字符串更改为当前子目录名称

将多个文件中的字符串更改为当前子目录名称

我有几个目录,每个目录都包含一个包含以下行的文件:

../a_a_q1.out ../a_a_q2.out ../a_a_q3.out

我想循环遍历所有子目录,并将该a_a部分更改为当前子目录名称。例如,如果一个子目录被调用awesome_directory,我希望这一行读取:

../awesome_directory_q1.out ../awesome_directory_q2.out ../awesome_directory_q3.out

我将如何实现这一目标?

我只想使用子目录名称。例如,我只需要 ( awesome_directory) 部分而不是完整交易 ( //something/server/user/other_stuff/more/awesome_directory)

答案1

在 bash 中分两步,这是一种方法 -

epwd=$(basename `pwd`)
sed -i "s/a_a/$epwd/g" <filename>

该变量$epwd包含一个转义的目录名称,可用于 sed。 sed 命令将所有出现的 a_a 替换为工作目录

编辑:原始答案的第一行已被编辑为仅包含当前目录名称,而不是完整路径。如果你想要完整路径使用

epwd=$(pwd|sed 's/\//\\\//g')

答案2

到目前为止我想出了这个。

var=("${PWD##*/}")

sed -i "s/a_a/$var/g" filename

答案3

set '%s_q1.out %s_q2.out %s_q3.out\n'
:|for d in several directories
do      cd  -P -- "$d" || ! break
        set "$1" "../${PWD##*/}"
        {   sed -ne'\|\( \.\./a_a_q[123]\.out\)\{3\}|q;s/.//p'
            printf "$@" "$2" "$2";  cut -c2-
        } <<-IN >./infile
        $(paste -d\  - ./infile)
        IN
done

这应该可以与 POSIXsedbashzshkshmkshshell 等一起使用。使用dashyashshell 时,此处文档不太可能得到常规文件的支持,因此您不能依赖lseek()支持共享输入所需的功能。在这些情况下,您应该切换到上述 shell 之一。

如果您使用 GNU,sed您会希望使用sed -une而不是仅仅使用sed -ne

这是一个细分:

  1. 首先我们set有一个参数,我们将printf一遍又一遍地使用 as 的格式字符串,并将$PWD和设置$OLDPWD.

  2. 接下来我们开始迭代中的项目several directories。无论这些是实际的目录还是符号链接,我们都会获得-P物理的、规范的路径名,$PWD并且set它是$2.

  3. 接下来发生的事情发生在heredoc重定向的底部。paste将所有内容读取./infile到 shell 为我们保护的某个安全临时文件中,同时在每一行前面添加一个空格。然后 shell 将该临时文件设置为 stdin 并./infile再次分配 - 但这次作为 stdout。

  4. sed很少进行编辑。在遇到匹配行之前,它会删除每行的第一个字符并p打印结果。一旦它遇到你的行,它q就会完全输入 - 不打印任何内容。

  5. printf打印../${PWD##*/}_q[123].out后跟一个换行符到标准输出,然后在离开的cut地方拾取标准输入sed(就在你的比赛线之后)并读出其余部分,同时从每个输入行中剥离第一个字节。

因此,整个编辑后的内容./infile最终会回到原来的位置。

哦,我确实测试过。

我更换了several directories对路径名进行了一些修改/tmp,然后...

{   seq 7
    echo '../a_a_q1.out ../a_a_q2.out ../a_a_q3.out'
    seq 9 14
    printf %s\\n '' '' ''
}  >/tmp/infile

...写出了一个/tmp/infile看起来像:

1
2
3
4
5
6
7
../a_a_q1.out ../a_a_q2.out ../a_a_q3.out
9
10
11
12
13
14



不过,在运行上面的代码片段后/tmp...

cat /tmp/infile

1
2
3
4
5
6
7
../tmp_q1.out ../tmp_q2.out ../tmp_q3.out
9
10
11
12
13
14



答案4

如果该a_a部分是恒定的并且您运行的是 Linux,那么您可以使用该rename实用程序。在 Debian 及其衍生版本上,请更改rename为,rename.ul因为该rename命令是一个不同的实用程序,它也可以完成此工作,但具有不同的语法。

使用循环遍历目录:

for d in */; do … done

调用rename重命名每个目录中的文件。

for d in */; do
  rename /a_a "/${d%/}" "$d"a_a*
done

相关内容