匹配whitelist.txt文件名并复制的Shell脚本无输出问题排查
从指定目录复制白名单匹配文件的脚本问题
我有一个whitelist.txt文件,内容是如下格式的文件名列表:
9853412_00000_0_0.vcf 7549682_00000_0_0.vcf 3589647_00000_0_0.vcf
需求是在指定的SOURCE目录中查找与该白名单内文件名匹配的文件,并将匹配到的文件复制到TARGET目录。
比如SOURCE目录有这些文件:
9853412_00000_0_0.vcf 7549682_00000_0_0.vcf 3589647_00000_0_0.vcf 8965423_00000_0_0.vcf 2547936_00000_0_0.vcf 5479241_00000_0_0.vcf
应该把前3个vcf文件复制到TARGET目录。
我试了以下两个脚本,运行时没有报错,但没有文件被复制,不知道原因:
第一个脚本:
#!/bin/sh SOURCE="/my/source/dir/*.vcf" TARGET="/my/target/dir/" while IFS= read -r line; do find $SOURCE -type f -name "$line" -exec cp {} $TARGET \; done < whitelist.txt
第二个脚本:
#!/bin/sh SOURCE="/my/source/dir/*.vcf" TARGET="/my/target/dir/" while IFS= read -r line; do find $SOURCE -type f -name "${line}" -exec cp '{}' $TARGET \; done < whitelist.txt
问题原因
- SOURCE变量用法错误:
find命令的第一个参数需要是目录路径,但你给SOURCE赋值了带通配符的"/my/source/dir/*.vcf"。shell会先展开通配符,导致find接收的是多个文件路径而非目录,此时find不会在目录内查找,而是直接处理这些文件,和-name条件完全不匹配,自然找不到目标文件。 - 空行干扰:
whitelist.txt末尾的空行会被循环读取,执行无效的find操作,但这不是文件未复制的主因。
修复后的脚本方案
方案1:用find指定目录查找(支持递归/非递归)
把SOURCE改为纯目录路径,让find在目录内匹配文件:
#!/bin/sh SOURCE="/my/source/dir" TARGET="/my/target/dir/" # 确保目标目录存在,避免cp报错 mkdir -p "$TARGET" while IFS= read -r line; do # 跳过空行 [ -z "$line" ] && continue # -maxdepth 1 表示只在SOURCE目录下查找,不递归子目录;需要递归则删除该参数 find "$SOURCE" -type f -maxdepth 1 -name "$line" -exec cp {} "$TARGET" \; done < whitelist.txt
方案2:直接用cp(非递归场景更高效)
如果不需要递归查找子目录,直接检查文件是否存在并复制:
#!/bin/sh SOURCE="/my/source/dir" TARGET="/my/target/dir/" mkdir -p "$TARGET" while IFS= read -r line; do [ -z "$line" ] && continue # 检查文件存在后再复制 if [ -f "$SOURCE/$line" ]; then cp "$SOURCE/$line" "$TARGET" fi done < whitelist.txt
方案3:用xargs批量处理(大文件列表更高效)
针对大体积的白名单文件,用xargs减少进程创建次数:
#!/bin/sh SOURCE="/my/source/dir" TARGET="/my/target/dir/" mkdir -p "$TARGET" # 过滤空行后批量复制,忽略文件不存在的错误提示 grep -v '^$' whitelist.txt | xargs -I {} cp -t "$TARGET" "$SOURCE/{}" 2>/dev/null
内容的提问来源于stack exchange,提问作者user20100946
相关产品推荐
相关产品推荐

