A bash script we use to extract the spectrometer usage statistics from “raw” data.
What it does: finds all raw spectra files (fid and sed) that were created within the period of a given number of days ago, and then gets from corresponding audit trail files pairs of dates when the spectra were measured, checks that they were not measured before the desired time period (to exclude wrpa’d datasets), duration of measurement, probehead, and user (both are extracted only for the most recent run, though) and saves to a CSV file. The latter can be further processed in Excel.
We use it to cross-check with the reservation system records. It works relatively well on our workstations (all CentOS 7) with TopSpin 3.5.7 and 4.1.4
To do: add popt detection
Suggestions and corrections are welcome
#!/bin/bash
# Get user input
# Check if number of days is provided as a parameter, otherwise prompt the user
if [[ -z "$1" ]]; then
read -p "Enter the number of days: " days
else
days="$1"
fi
# path="/opt/nmrdata/"
# or check if path is provided as a parameter, otherwise prompt the user
if [[ -z "$2" ]]; then
read -p "Enter the path to search: " path
else
path="$2"
fi
# Validate input
if [[ ! -d "$path" ]]; then
echo "Error: The path '$path' does not exist."
exit 1
fi
if ! [[ "$days" =~ ^[0-9]+$ ]]; then
echo "Error: Number of days must be a valid integer."
exit 1
fi
# Output file with unique name including hostname
output_file="summary-$(uname -n)-$(date +%Y-%m-%d_%H-%M-%S)-last-$days-days.csv"
# Initialize the output file
> "$output_file"
# Convert input days to a cutoff date (in epoch for comparison)
cutoff_date_epoch=$(date -d "-$days days" +%s)
# Find all spectra files created within the specified number of days
files=$(find "$path" -type f -mtime -$days \( -name 'fid' -o -name 'ser' \))
# Check if any files were found
if [[ -z "$files" ]]; then
echo "No data found in the specified path."
exit 0
fi
# Convert timestamps to a unified format
convert_timestamp() {
local timestamp=$1
echo $(date -d "${timestamp//[<>]/ }" +"%Y-%m-%d %H:%M:%S")
}
# Regex for matching timestamps (Perl-compatible regex)
timestamp_regex='\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}\.\d{3}[ ]?[\+\-]\d{4}'
# Set IFS to handle filenames with spaces
IFS=$'\n'
# Process each file
for file in $files; do
# Get the directory path
# echo "Found file: ${file}"
dir_path=$(dirname "$(realpath "$file")")
echo "Processing directory: $dir_path"
prev_timestamp=""
while IFS= read -r line; do
# Check if the line contains a valid timestamp
if echo "$line" | grep -qP "$timestamp_regex"; then
current_timestamp=$(echo "$line" | grep -oP "$timestamp_regex")
# Check if the line contains "started at"
if [[ $line =~ "started at" ]]; then
start_timestamp=$current_timestamp
unified_start_ts=$(convert_timestamp "$start_timestamp")
unified_prev_ts=$(convert_timestamp "$prev_timestamp")
# Compare timestamps using epoch values
start_epoch=$(date -d "$start_timestamp" +%s)
end_epoch=$(date -d "$prev_timestamp" +%s)
if [[ $start_epoch -gt $cutoff_date_epoch ]]; then
duration=$((end_epoch - start_epoch))
probe=$(grep -o '##$PROBHD= .*' "$dir_path"/acqus | cut -d" " -f2-)
user=$(grep -o '##OWNER= .*' "$dir_path"/acqus | cut -d" " -f2-)
# Write to the output file, clean commas, brackets, carrier returns
printf "%s\n" "$unified_start_ts, $unified_prev_ts, $duration, ${dir_path//,/}, ${probe//[<>.\r]/}, ${user//$'\r'/}" >> "$output_file"
fi
# Reset timestamps
start_timestamp=""
prev_timestamp=""
else
prev_timestamp=$current_timestamp
fi
fi
done < "$dir_path"/audita.txt
done
unset IFS
# Sort and remove duplicates
sort -u -t ',' -k2,2 "$output_file" | sort -t ',' -k2,2 > "${output_file}.sorted"
mv "${output_file}.sorted" "$output_file"
# Add header
sed -i '1s/^/Start Time, End Time, Duration (sec), Directory, Probe ID, User\n/' "$output_file"
echo "Script finished. Results saved to '$output_file'"