Linux 如何将包含目录作为前缀添加到复制的文件名中?
问题:我有一堆文件被分割到多个目录中,它们都有相同的名称(input.txt) 我的目标:我想首先将所有这些内容复制到一个新目录,同时将包含的目录添加为suffux,以避免它们之间的混淆并防止覆盖。这是我试图做的工作的基础:Linux 如何将包含目录作为前缀添加到复制的文件名中?,linux,bash,shell,cp,Linux,Bash,Shell,Cp,问题:我有一堆文件被分割到多个目录中,它们都有相同的名称(input.txt) 我的目标:我想首先将所有这些内容复制到一个新目录,同时将包含的目录添加为suffux,以避免它们之间的混淆并防止覆盖。这是我试图做的工作的基础: cp -nr /foo/bar/*/input.txt /new/path/ 我该怎么办 如果/old/目录中的我的文件结构包含文件夹,请响应以下注释: /old/directory/1/input.txt /old/directory/2/input.txt /old/
cp -nr /foo/bar/*/input.txt /new/path/
我该怎么办
如果/old/目录中的我的文件结构包含文件夹,请响应以下注释:
/old/directory/1/input.txt
/old/directory/2/input.txt
/old/directory/3/input.txt
这是我所需输出的一个示例:
/新的/directory/应包含:
1input.txt
2input.txt
3input.txt
谢谢好吧,不幸的是,没有一种明显的方式可以在一行中做到这一点,也没有一种方式不难理解。也许有一种方法可以用rsync实现,我相信比我更聪明的人可以用awk实现,但在我看来,你最好编写一个脚本,甚至编写一个自定义二进制文件来实现这一点
find . -name input.txt | while read line
do
cp "$line" /new/path/`echo $line | cut -d '/' -f3- | sed 's/\//_/'`
done
请注意,您可能必须更改cut命令的-f3-部分,以便选择要以哪个目录名作为后缀开头。好吧,最糟糕的是,没有一种明显的方式在一行中执行此操作,而不是一种不难理解的方式。也许有一种方法可以用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
##:仅在没有文件/目录的情况下,*glob不会自行展开。
shopt-s nullglob
files=(foo/bar/*/input.txt)
对于“${files[@]}”中的文件;做
new_file=${file/\/\/\}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
echo cp-v“$file”new/path/“$new_文件”
完成
根据OP的要求,这里是新的答案
#/usr/bin/env bash
shopt-s nullglob
##:尽管文件=(/old/directory/{1..3}/input.txt)
##:可以替换,不需要nullglob
files=(/old/directory/*/input.txt)
对于“${files[@]}”中的文件;做
tmp=${file%[0-9]*}
新建文件=${file#*$tmp}
echo cp-v“$file”new/path/“${new\u file//\/}”
完成
另一个选项是使用
/
作为分隔符拆分字段
#/usr/bin/env bash
##:如果没有文件/目录,请不要展开文本glob*
shopt-s nullglob
##:将整个路径和文件保存在数组中。
files=(/old/directory/*/input.txt)
对于“${files[@]}”中的文件;做
如果s='/'read-ra path一种方法是使用数组保存文件,而且由于文件名上不允许使用/
,另一种方法是将其更改为其他内容,例如下划线
#/usr/bin/env bash
##:仅在没有文件/目录的情况下,*glob不会自行展开。
shopt-s nullglob
files=(foo/bar/*/input.txt)
对于“${files[@]}”中的文件;做
new_file=${file/\/\/\}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
echo cp-v“$file”new/path/“$new_文件”
完成
根据OP的要求,这里是新的答案
#/usr/bin/env bash
shopt-s nullglob
##:尽管文件=(/old/directory/{1..3}/input.txt)
##:可以替换,不需要nullglob
files=(/old/directory/*/input.txt)
对于“${files[@]}”中的文件;做
tmp=${file%[0-9]*}
新建文件=${file#*$tmp}
echo cp-v“$file”new/path/“${new\u file//\/}”
完成
另一个选项是使用/
作为分隔符拆分字段
#/usr/bin/env bash
##:如果没有文件/目录,请不要展开文本glob*
shopt-s nullglob
##:将整个路径和文件保存在数组中。
files=(/old/directory/*/input.txt)
对于“${files[@]}”中的文件;做
IFS='/'read-ra path这将实现这一技巧,并处理名称中可能包含空格(或任何其他奇数字符)的任何目录
这将实现这一技巧,还可以处理名称中可能包含空格(或任何其他奇数字符)的任何目录
不完全是吗?我想将所有文件移到同一个文件夹中。这似乎是将整个目录结构复制到新位置,还是我做错了?啊,不,我误解了-你是对的。我想你的意思是你想要整个目录结构。我将编辑我的答案。当我这样做时,我会得到以下错误:find:warning:Unix文件名通常不包含斜杠(虽然路径名包含斜杠)。
另外:find:path必须在表达式前面:
/new/path/input.txt'`和find:predicate
-name'后面可能有无引号的模式?`不完全?我想将所有文件移到同一个文件夹中。这似乎是将整个目录结构复制到新位置,还是我做错了?啊,不,我误解了-你是对的。我想你的意思是你想要整个目录结构。我将编辑我的答案。执行此操作时,会出现以下错误:find:警告:Unix文件名通常不包含斜杠(尽管路径名包含斜杠).
另外:find:path必须在表达式之前:
/new/path/input.txt'`和find:predicate之后可能有无引号的模式
-name'?`请通过给出示例输入文件名和所需的输出文件名来澄清“将包含目录作为后缀添加”的含义。我现在正在回答问题。请通过给出示例输入文件名和所需输出来澄清“添加包含目录作为后缀”的含义。我现在正在回答问题。好吧,这真的很接近我想要的!我想这会打印出整个路径
$ 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