输入:
- 包含大量文件的文件夹(具有复杂的文件层次结构)
- 包含文件名的 JSON/CSV 文件
输出:
- 一个新文件夹,其中包含从输入文件夹复制的文件和 CSV/JSON 文件中的匹配文件名
我对批处理/sed/awk 的了解有限,因此欢迎提出任何想法/建议。
谢谢!
我对批处理/sed/awk 的了解有限,因此欢迎提出任何想法/建议。
谢谢!
正如上面评论中提到的,bash/sed/awk 不是解析 JSON 的理想选择。既然您暗示 CSV 是一种选择,我会说这是您最好的选择。
由于我不知道这是否是一项任务,并且您还没有提及您尝试过的内容,因此我将避免为您编写完整的脚本。相反,这里是核心位的快速浏览,希望能帮助您前进。
而且由于您没有提供示例输入文件,我将补上一个。假设您有一个这样的输入 CSV 文件:
$ cat in.csv
john,hello/world/domination.txt,10
ruth,some_file.txt,20
sarah,jessica/parker.jpg,80
最简单的方法是使用while
循环和read
:
$ while IFS=',' read -r NAME FILENAME AGE; do echo "$FILENAME"; done < in.csv
hello/world/domination.txt
some_file.txt
jessica/parker.jpg
in/my documents/empty.file
请注意,我们已将IFS
(内部文件分隔符)临时更改为逗号,以将输入 CSV 行拆分为字段。
假设在您的脚本中,您有一个基本路径(您的“...文件夹包含很多文件(具有复杂的文件层次结构)”)和一个目标目录,如下所示:
BASE_PATH="/some/source/"
DEST_PATH="/the/destination/"
对于 CSV 文件中的每个文件名——比如说hello/world/domination.txt
——你想最终从/some/source/hello/world/domination.txt
to复制/the/destination/hello/world/domination.txt
,则涉及 3 个步骤:
通过附加字符串来创建FROM
和路径:TO
FROM="${BASE_PATH}/${FILENAME}"
TO="${DEST_PATH}/${FILENAME}"
确保目标目录存在。我们dirname
用来提取目录的名称,并mkdir -p
在目录不存在时递归地创建目录:
mkdir -p "$(dirname $TO)"
执行实际复制
cp "$FROM" "$TO"
mkdir
参数周围的引号cp
确保带有空格的路径不被视为单独的参数。
请注意,为简洁起见,我省略了错误检查。在生产脚本中,您通常希望包含检查以确保源文件存在且可读,并且目标路径可写。
假设您已经分配了BASE_PATH
and DEST_PATH
:
while IFS=',' read -r NAME FILENAME AGE
do
FROM="${BASE_PATH}/${FILENAME}"
TO="${DEST_PATH}/${FILENAME}"
mkdir "$(dirname $TO)"
cp "$FROM" "$TO"
done < in.csv
你没有给我们太多让我们继续下去,所以我会假设
您使用 CSV 文件
位于源目录的根目录
被格式化为file1,file2,...
这file1
只是一个文件名,而不是该文件的完整路径。
在这种情况下(这是最简单的情况),您可以尝试类似
#!/bin/bash
# some renaming for easier read
srccsv="$(basename "$1")"
srcdir="$(dirname "$1")"
trgtdir="$2"
# perform the copy
set +o posix
cp <(IFS=,; \
while read filename; do \
find "$srcdir" -type f -name "$filename" -print0; \
done < "$srccsv") "$trgtdir"
然后通过运行它
./cp_csv.sh path/to/your/csv path/to/your/targetdir
假设您已将此脚本命名为cp_csv.sh
。
注意:它是特定于 bash 的(因为进程替换),我没有对此进行测试(这里已经很晚了..),但我不明白为什么会失败。
如果您使用的是 JSON 输入文件,那么在 bash 中解析会更加痛苦。正如@jordanm 所指出的, bash/sed/awk 不是正确的工具。