ILMostro_7
ILMostro_7

Reputation: 1492

How to select filetypes in bash script or perl and act based on the type

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

Essentially, what's the best way, in terms of portability or readability, to create a test something like the following pseudo "code"?

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

Answers (2)

R4F6
R4F6

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

Charles Duffy
Charles Duffy

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

Related Questions