根据文本文件中的列表从一系列目录中复制文件
Copying files from a series of directories based off a list in a text file
我试图在 for
循环中使用 rsync
或 cp
来复制与 [=18= 中新行中存储的 200 个名称列表相匹配的文件] 文件匹配具有 .pdbqt
扩展名的文件名,这些文件名位于具有一个父文件夹的一系列子目录中。 .txt
文件如下所示:
file01
file02
file08
file75
file45
...
我尝试通过以下命令使用 rsync:
rsync -a /home/ubuntu/Project/files/pdbqt/*/*.pdbqt \
--files-from=/home/ubuntu/Project/working/output.txt \
/home/ubuntu/Project/files/top/
当我运行收到rsync命令时:
rsync error: syntax or usage error (code 1) at options.c(2346) [client=3.1.2]
我已经编写了一个 bash 脚本,试图让它工作:
#!/bin/bash
for i in "$(cat /home/ubuntu/Project/working/output.txt | tr '\n' '')"; do
cp /home/ubuntu/Project/files/pdbqt/*/"$i".pdbqt /home/ubuntu/Project/files/top/;
done
我知道 cat
不是一个很好用的命令,但我想不出替代解决方案,因为我对使用 bash 还是个新手。 运行 我收到以下错误:
tr: when not truncating set1, string2 must be non-empty
cp: cannot stat '/home/ubuntu/Project/files/pdbqt/*/.pdbqt': No such file or directory
我假设 cp
错误是由于 tr 错误而引发的,但我不确定如何摆脱从新行分隔列表中读取的 \n
.
预期的结果是 /pdbqt/
的子目录中包含 12000 个 .pdbqt
文件,output.txt 列表中的 200 个文件将从这些子目录复制到 /top/
目录.
当您的数据已经在 shell 变量中时,for
循环很好。从文件中读取数据时,while ... read
循环效果更好。在你的情况下,尝试:
while IFS= read -r file; do cp -i -- /home/ubuntu/Project/files/pdbqt/*/"$file".pdbqt /home/ubuntu/Project/files/top/; done </home/ubuntu/Project/working/output.txt
或者,如果您发现多行版本更具可读性:
while IFS= read -r file
do
cp -i -- /home/ubuntu/Project/files/pdbqt/*/"$file".pdbqt /home/ubuntu/Project/files/top/
done </home/ubuntu/Project/working/output.txt
工作原理
while IFS= read -r file; do
这会启动一个 while
循环,一次读取一行。 IFS=
告诉 bash 不要从行中截断白色 space 并且 -r
告诉 read
不要破坏反斜杠。该行存储在名为 file
.
的 shell 变量中
cp -i -- /home/ubuntu/Project/files/pdbqt/*/"$file".pdbqt /home/ubuntu/Project/files/top/
这将复制文件。 -i
告诉 cp
在覆盖现有文件之前询问。
done </home/ubuntu/Project/working/output.txt
这标志着 while
循环的结束,并告诉 shell 从 /home/ubuntu/Project/working/output.txt
获取循环的输入
Project/files/pdbqt/*
中的目录或文件 *.pdbqt
的名称中是否包含破折号 (-
)?
错误显示 rsync 源代码中的行 options.c
"Your options have been rejected by the server.\n"
这让我认为它正在将您的 glob 中的 inode (files/dirs) 解释为 rsync 选项。
for i in $( < /home/ubuntu/Project/working/output.txt LC_CTYPE=C tr '\n' ' ' )
do
cp /home/ubuntu/Project/files/pdbqt/*/"${i}.pdbqt" /home/ubuntu/Project/files/top/
done
我认为你的 cat tr 缺少 space
cat /home/ubuntu/Project/working/output.txt | tr '\n' ' '
对while
和read
的使用比我的好。
你的想法是正确的rsync
。 rsync
提供选项 --files-from="yourfile"
,它将 rsync
您 textfile
中的所有文件(相对于您接下来指定的基本目录)到目的地(host:/dest/path
或在本地单独使用 /dest/path
)
您需要指定 --no-R
来告诉 rsync
不要使用相对文件名,因为 --files-from=
将基本路径作为下一个参数。例如,要将文本文件中的所有文件传输到指定文件位置在当前目录中的某个远程主机,您可以使用:
rsync -uai --no-R --files-from="textfile" ./ host:/dest/path
命令基本上指定您从 textfile
读取要传输的名称,文件将在 ./
(当前目录)下找到,然后您将文件传输到 host:/dest/path
在您指定的 host
上。您可以查看 man 1 rsync 了解完整详情。
我试图在 for
循环中使用 rsync
或 cp
来复制与 [=18= 中新行中存储的 200 个名称列表相匹配的文件] 文件匹配具有 .pdbqt
扩展名的文件名,这些文件名位于具有一个父文件夹的一系列子目录中。 .txt
文件如下所示:
file01
file02
file08
file75
file45
...
我尝试通过以下命令使用 rsync:
rsync -a /home/ubuntu/Project/files/pdbqt/*/*.pdbqt \
--files-from=/home/ubuntu/Project/working/output.txt \
/home/ubuntu/Project/files/top/
当我运行收到rsync命令时:
rsync error: syntax or usage error (code 1) at options.c(2346) [client=3.1.2]
我已经编写了一个 bash 脚本,试图让它工作:
#!/bin/bash
for i in "$(cat /home/ubuntu/Project/working/output.txt | tr '\n' '')"; do
cp /home/ubuntu/Project/files/pdbqt/*/"$i".pdbqt /home/ubuntu/Project/files/top/;
done
我知道 cat
不是一个很好用的命令,但我想不出替代解决方案,因为我对使用 bash 还是个新手。 运行 我收到以下错误:
tr: when not truncating set1, string2 must be non-empty
cp: cannot stat '/home/ubuntu/Project/files/pdbqt/*/.pdbqt': No such file or directory
我假设 cp
错误是由于 tr 错误而引发的,但我不确定如何摆脱从新行分隔列表中读取的 \n
.
预期的结果是 /pdbqt/
的子目录中包含 12000 个 .pdbqt
文件,output.txt 列表中的 200 个文件将从这些子目录复制到 /top/
目录.
for
循环很好。从文件中读取数据时,while ... read
循环效果更好。在你的情况下,尝试:
while IFS= read -r file; do cp -i -- /home/ubuntu/Project/files/pdbqt/*/"$file".pdbqt /home/ubuntu/Project/files/top/; done </home/ubuntu/Project/working/output.txt
或者,如果您发现多行版本更具可读性:
while IFS= read -r file
do
cp -i -- /home/ubuntu/Project/files/pdbqt/*/"$file".pdbqt /home/ubuntu/Project/files/top/
done </home/ubuntu/Project/working/output.txt
工作原理
while IFS= read -r file; do
这会启动一个
while
循环,一次读取一行。IFS=
告诉 bash 不要从行中截断白色 space 并且-r
告诉read
不要破坏反斜杠。该行存储在名为file
. 的 shell 变量中
cp -i -- /home/ubuntu/Project/files/pdbqt/*/"$file".pdbqt /home/ubuntu/Project/files/top/
这将复制文件。
-i
告诉cp
在覆盖现有文件之前询问。done </home/ubuntu/Project/working/output.txt
这标志着
while
循环的结束,并告诉 shell 从/home/ubuntu/Project/working/output.txt
获取循环的输入
Project/files/pdbqt/*
中的目录或文件 *.pdbqt
的名称中是否包含破折号 (-
)?
错误显示 rsync 源代码中的行 options.c
"Your options have been rejected by the server.\n"
这让我认为它正在将您的 glob 中的 inode (files/dirs) 解释为 rsync 选项。
for i in $( < /home/ubuntu/Project/working/output.txt LC_CTYPE=C tr '\n' ' ' )
do
cp /home/ubuntu/Project/files/pdbqt/*/"${i}.pdbqt" /home/ubuntu/Project/files/top/
done
我认为你的 cat tr 缺少 space
cat /home/ubuntu/Project/working/output.txt | tr '\n' ' '
while
和read
的使用比我的好。
你的想法是正确的rsync
。 rsync
提供选项 --files-from="yourfile"
,它将 rsync
您 textfile
中的所有文件(相对于您接下来指定的基本目录)到目的地(host:/dest/path
或在本地单独使用 /dest/path
)
您需要指定 --no-R
来告诉 rsync
不要使用相对文件名,因为 --files-from=
将基本路径作为下一个参数。例如,要将文本文件中的所有文件传输到指定文件位置在当前目录中的某个远程主机,您可以使用:
rsync -uai --no-R --files-from="textfile" ./ host:/dest/path
命令基本上指定您从 textfile
读取要传输的名称,文件将在 ./
(当前目录)下找到,然后您将文件传输到 host:/dest/path
在您指定的 host
上。您可以查看 man 1 rsync 了解完整详情。