如何在bash脚本或perl中选择文件类型并根据类型进行操作



暂时忽略此处仅作为示例使用的特定文件类型的任何问题。

给定一个包含多种类型文件的目录,如markdown格式的README文件、git版本控制文件、PEM密钥和其他随机文件类型,就可移植性甚至可读性而言,只选择目录中的PEM密钥并将其移动到任意位置的最佳方式是什么?

一个可能的选项是使用file工具,该工具返回文件类型。例如:

$ file randomly-named-file
randomly-named-file: PEM RSA private key

从本质上讲,就可移植性或可读性而言,创建类似以下伪"代码"的测试的最佳方式是什么

if file $1 is PEM
mv $1 /some/other/dir
fi

首选Bash;不过,如果需要,perl解决方案是可以接受的。

最初的问题源于在Mac OSX平台上的使用,该平台具有较高的用例,并且需要在Linux(基于RHEL的Gentoo)平台之间进行可移植性。

file版本是5.31,支持-print0

值得注意的是,file工具显然是我想到的第一选择。如果有其他便携式解决方案,它不必使用该工具。

需要file -0的合理实现(受libmagic的所有常见限制)可能如下所示:

#!/usr/bin/env bash
#              ^^^^- NOT /bin/sh; requires bash-specific syntax.
while IFS= read -r -d '' filename && read -r type; do
type=${type#": "}
if [[ $type = *"PEM RSA private key"* ]]; then
printf 'Found file: %qn' "$filename"
fi
done < <(file -0 -- *)

-0参数告诉file在每个文件名之后打印一个NUL;IFS= read -r -d ''读取到第一个NUL,因此它只消耗文件名,而read -r type消耗每行的其余部分。

这使得可以从列表中的类型中消除名称的歧义,即使这些名称包含冒号、换行符或其他令人惊讶的字符。如果没有-0,则需要为要测试的每个文件启动一个单独的file副本,并附带相关的性能影响。

如果由于某种原因,您不能依赖file,您可以尝试使用head检查文件中的PEM文件标准头,如下所示:

for file in ./*; do
echo "Examining file: $file"
first_line=$(head -n 1 "$file")
if [ "$first_line" = "-----BEGIN ENCRYPTED PRIVATE KEY-----" ]; then
echo "Found PEM file"
mv example.pem /my/arbitrary/dir
fi
done

我用以下测试文件创建了一个小目录:

$ ls
pretend.pdf example.pem script.sh   text_file.txt

针对该目录运行脚本会得到以下结果:

$ ./script.sh 
Examining file: ./pretend.pdf
Examining file: ./example.pem
Found PEM file
Examining file: ./script.sh
Examining file: ./text_file.txt

最新更新