我面临着一个复杂的挑战。我对linux和脚本不是很实用,但我需要解决一个问题。我有一个文件 list.txt,其中包含两列,第一列是对象的名称,第二列是变量。现在我想使用此信息来复制特定目录中的特定文件。例如:
工作目录是这样的:/nfs/BioGPSDB/pockets/MD/fixed/1/
这是文件/home/tommaso/Desktop/list.txt
:
121p1_004_______________ GCP
13gs1_001_______________ SAS
1am42_003_______________ GNP
1bmq1_003_______________ MNO
ecc...
在下面显示的工作目录中,有很多目录,其中一些目录的名称与文件“list.txt”第一列中存在的对象名称的前 5 个字符相关。例如:1j4r3、1t403、121p1
、1sdr4、1bmq1
ecc...
每个目录中都有很多文件。我需要,对于文件“list.txt”的每一行,使用第一列选择目录,进入此目录,选择感兴趣的文件并将其复制到另一个目录中(/home/tommaso/Desktop/pdb_files)
。感兴趣的文件的调用方式类似于文件“list.txt”第二列中报告的变量。例子:
directory: /nfs/BioGPSDB/pockets/MD/fixed/1/121p1
File of interest: "GCP_?.pdb" where "?" is one character (letter or number)
Final directory: /home/tommaso/Desktop/pdb_files
所以最后在目录中/home/tommaso/Desktop/pdb_files
我必须拥有这样的所有文件:
GCP_?.pdb, SAS_?.pdb, GNP_?.pdb, MNO_?.pdb ecc..
因此,脚本应该读取该list.txt
文件,并且对于第一列每行中的前 5 个字符命名的每个目录,它应该复制第二列中名为变量的文件,并将扩展名复制"_?.pdb"
到所有文件都将出现的最终目录中。
我希望已经足够清楚,我希望找到愿意帮助我的人,因为我不知道从哪里开始!
答案1
您应该能够使用以下方法来做到这一点:
cd /nfs/BioGPSDB/pockets/MD/fixed/1/
while IFS= read -r line
do
echo cp -i -- "${line:0:5}/${line##* }"_?.pdb /home/tommaso/Desktop/pdb_files/
done < /home/tommaso/Desktop/list.txt
当对打印的命令感到满意时,删除echo
来实际复制文件cp
。
假设你只有一文件${line##* }"_?.pdb
与每个目录中的模式匹配,您还可以通过将命令行_?.pdb
更改cp
为:
cp -i -- "${line:0:5}/${line##* }"_?.pdb \
"/home/tommaso/Desktop/pdb_files/${line##* }_?.pdb"
该-i
选项cp
指示它在覆盖目标目录中的文件之前进行询问;根据您的要求,这不是必需的,但当来自不同目录的文件被复制/移动到单个目录时,这是有意义的。
该脚本假定每个文件名片段前面都有一个或多个空格list.txt
。如果适用,请将 中的空格替换${line##* }
为紧邻文件名片段之前的字符。
多种 shell(bash、ksh93、zsh、busybox ash 等)都支持这种扩展,即“替换为从索引 0(第一个字符)开始的变量${line:0:5}
的五个字符子字符串”,line
但不是 POSIX 的一部分,特别是在 dash 中不可用。