Reputation: 1492
For the moment, ignore any issues with the specific file type used here as an example only.
Given a directory with multiple types of files, like a README file in markdown format, git version control files, PEM keys, and other random file types, what's the best way, in terms of portability or even readability, to select ONLY the PEM keys in the directory and move those over to an arbitrary location?
One possible option was to use the file
tool, which returns the file type. For example:
$ file randomly-named-file
randomly-named-file: PEM RSA private key
if file $1 is PEM
mv $1 /some/other/dir
fi
Bash is preferred; though, perl solution is acceptable if necessary.
The original question stemmed from use on a Mac OSX platform with high use-case of and needed portability between Linux (RHEL-based, Gentoo) platforms.
The file
version is 5.31, supporting -print0
, for what it's worth.
It might be worth noting, that the file
tool is just the obvious first choice I thought of. It does NOT have to be using that tool if other portable solutions are available.
Upvotes: 1
Views: 75
Reputation: 792
If, for some reason, you cannot rely on file
, you can try the using head
to inspect the file for the PEM file standard header, like so:
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
I created a small directory with the following test files:
$ ls
pretend.pdf example.pem script.sh text_file.txt
Running the script against this directory gives the following results:
$ ./script.sh
Examining file: ./pretend.pdf
Examining file: ./example.pem
Found PEM file
Examining file: ./script.sh
Examining file: ./text_file.txt
Upvotes: 2
Reputation: 295659
A reasonable implementation (subject to all the usual limitations of libmagic) requiring file -0
might look like the following:
#!/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: %q\n' "$filename"
fi
done < <(file -0 -- *)
The -0
argument tells file
to print a NUL after each filename; IFS= read -r -d ''
reads up to the first NUL, so it thus consumes only the filename, whereas read -r type
consumes the rest of each line.
This makes it possible to disambiguate names from types in the list, even if those names contain colons, newlines, or other surprising characters. If you didn't have -0
, you'd need to start a separate copy of file
for each file you wanted to test, with the associated performance hit.
Upvotes: 2