如何将包含目录作为前缀添加到复制的文件名? 概念证明

问题:我有一堆文件分散在多个目录中,每个目录都具有相同的名称(input.txt)。

我要做什么:我想首先将所有这些复制到新目录,同时将包含目录添加为后缀,以避免它们之间的混淆并防止覆盖。这是我要做的事的基础:

cp -nr /foo/bar/*/input.txt /new/path/

我从这里去哪里?

如果我的/ old /目录中的文件结构包含文件夹,请回应以下评论:

/old/directory/1/input.txt
/old/directory/2/input.txt
/old/directory/3/input.txt

这是我想要的输出的一个示例: / new / directory /应包含:

1input.txt
2input.txt
3input.txt

谢谢

caiczy000 回答:如何将包含目录作为前缀添加到复制的文件名? 概念证明

好消息,令人难过的是,没有一种明显的方式可以做到这一点-也不是一种并非毫无道理地难以理解的方式。也许有一种方法可以使用rsync进行操作,而且我敢肯定有人比我在awk中更聪明,但是我认为最好还是编写脚本,甚至编写一个自定义二进制文件来执行此操作为你。

find . -name input.txt | while read line
do
    cp "$line" /new/path/`echo $line | cut -d '/' -f3- | sed 's/\//_/'`
done

请注意,您可能必须更改cut命令的-f3-部分,以便选择要以后缀开头的目录名称。

,

一种方法是使用数组保存文件,而且由于文件名不允许使用/,因此可以将其更改为其他内容,例如下划线。

#!/usr/bin/env bash

##: Just in case there are no files/directories the * glob will not expand by itself.

shopt -s nullglob 

files=(foo/bar/*/input.txt)

for file in "${files[@]}"; do
  new_file=${file//\//_}  ##: Replace all /'s with an _ by Parameter Expansion
  echo cp -v "$file" new/path/"$new_file"
done


根据OP的要求,这是新答案。

#!/usr/bin/env bash

shopt -s nullglob

##: Although files=(/old/directory/{1..3}/input.txt)
##: can be a replacement,no need for nullglob

files=(/old/directory/*/input.txt)

for file in "${files[@]}"; do
  tmp=${file%[0-9]*}
  new_file=${file#*$tmp}
  echo cp -v "$file" new/path/"${new_file//\//}"
done

另一种选择是使用/作为分隔符来拆分字段。

#!/usr/bin/env bash

##: Do not expand a literal glob * if there are no files/directories
shopt -s nullglob

##: Save the whole path and files in an array.
files=(/old/directory/*/input.txt)

for file in "${files[@]}"; do
  IFS='/' read -ra path <<< "$file" ##: split via / and save in an array
  tmp=${path[@]:(-2)}  ##: Remain only the last 2,e.g. 1 input.txt
  new_file=${tmp// }   ##: Remove the space,becomes 1input.txt
  echo cp -v "$file" new/path/"$new_file"
done
  • 如果您认为输出正确,请删除echo

  • 很容易理解该文件来自哪个目录,只需用/

  • 替换得分不足即可。
,

这可以解决问题,还可以处理名称中可能带有空格(或其他奇数字符)的所有目录。

#!/bin/bash

tld=./old/directory
newpath=./new/directory

while IFS= read -r -d $'\0' file; do
   tmp="${file#*${tld}/}"
   echo cp "$file" "$newpath/${tmp//\//}"
done < <(find "$tld" -type f -name "input.txt" -print0)

概念证明

$ tree ./old/directory/
./old/directory/
├── 1
│   └── input.txt
├── 2
│   └── input.txt
└── 3
    ├── 3a
    │   └── input.txt
    └── input.txt

4 directories,4 files


$ ./mvinput.sh
cp ./old/directory/3/input.txt ./new/directory/3input.txt
cp ./old/directory/3/3a/input.txt ./new/directory/33ainput.txt
cp ./old/directory/1/input.txt ./new/directory/1input.txt
cp ./old/directory/2/input.txt ./new/directory/2input.txt
本文链接:https://www.f2er.com/2305872.html

大家都在问