由于我正在准备一本书,所以我收集了大量花卉图片。我只会使用其中的一些图片,它们包含在一个名为choosen.txt(实际上是一个csv)的文件中。我必须从按以下方式组织的文件夹树中挑选出选定的图片:
Pictures
├── Flowers 2020
│ ├── 1.- Spring 2020
│ ├── 2.- Summer 2020
│ ├── 3.- Autumn 2020
│ └── 4.- Winter 2020
└── Flowers 2021
├── 1.- Spring 2021
├── 2.- Summer 2021
├── 3.- Autumn 2021
└── 4.- Winter 2021
10 directories, 5260 files
并将每张选定的花朵图片复制到名为 Chosen-ones 的新文件夹中(例如)。希望我已经正确解释了我需要做什么。
以下是 csv 文件的几行chosen.txt
DSC10233.jpg
DSC10276.jpg
DSC10288.jpg
DSC10399.jpg
DSC10448.jpg
DSC10489.jpg
DSC10492.jpg
是否可以使用 Bash 或者 Python 脚本?
提前致谢。
答案1
当然,您可以使用一个非常小的 Bash 脚本来完成此操作。
我假设您chosen.txt
的主目录中有该列表,其中 Pictures 是其子目录。如果不是这种情况,请相应地调整路径。
首先创建要将文件移动到的目录。我假设您刚刚打开了一个终端,并且您位于主目录中。您可以稍后移动该目录。
mkdir ChosenOnes
现在检查您是否可以使用这样的列表找到正确的文件:
while read -r line; do find Pictures -name "$line" -ls; done < chosen.txt
如果结果看起来正确,您可以通过调整命令来复制文件:
while read -r line; do find Pictures -name "$line" -exec cp -vt ChosenOnes {} \; ; done < chosen.txt
我们可以让它看起来更好一些:
#!/bin/bash
# read our list and
while read -r line; do
# find the files in it and copy them to the new directory
find Pictures -name "$line" -exec cp -vt ChosenOnes {} \;
done < chosen.txt
解释
while read -r line; do things; done < input-file
只要条件成立,循环while
就会继续执行某项操作。这里我们要求逐行读取列表。每一行都将被放入变量中,line
以便我们可以在其上运行一些命令。当我们完成该行上的命令后,将读取下一行,直到文件中的行数用完为止。find path -name "$line"
该find
命令从给定路径(本例中为图片)向下进行递归搜索。这里我们使用该-name
选项查找与列表中的名称匹配的文件。-ls
该find
命令有一个选项可以列出找到的文件。这对于在采取任何行动之前检查找到的内容很有用-exec command {} \;
find选项-exec
对已找到的文件运行给定的命令(由 表示{}
)cp -vt
选项-v
makescp
告诉我们它在做什么。-t
选项指定目标(我们在它之后立即给出目标目录);否则目标将被视为最后一个参数。
答案2
是的,命令行上有几种方法可以做到这一点。
假设您只有一个文件名列表(没有路径),您可以使用循环while
读取“chosen.txt”文件,find
查找源文件夹中的文件,然后使用另一个while
循环复制它们。
定义变量使您可以重复使用长命令而无需编辑它。
list="/path/to/chosen.txt"
source="/path/to/Pictures"
dest="/path/to/destination"
cat "chosen.txt" \
| while read n; do
find "$source" -name "$n" \
| while read f; do
cp "$f" "$dest/"
done
done
或者在一行中:
cat "chosen.txt" | while read n; do find "$source" -name "$n" | while read f; do cp "$f" "$dest/"; done; done
另一种方法是,如果您的原始 .csv 文件也包含文件路径,则可以从中构建一个列表。然后,您可以使用rsync
选项--files-from=
复制它们,同时保留源的原始目录结构。