I am completely new to bash scripting. I am trying to write a script in order to read line by line recent_log.txt
which has the following content:
admin@bi01:/var/cache/logs$ head recent_log.txt ./calisto/tomcat6-energy/calls.log.2016-03-05 ./calisto/tomcat6-energy/calls_flush.log.2016-03-05.gz ./calisto/tomcat6-energy/catalina.2016-03-05.log.gz ./calisto/tomcat6-energy/energy-receive.log.2016-03-05.gz ./calisto/tomcat6-energy/energy.log.2016-01-01.gz ./calisto/tomcat6-energy/energy.log.2016-01-02.gz ./calisto/tomcat6-energy/energy.log.2016-01-03.gz ./calisto/tomcat6-energy/energy.log.2016-01-04.gz ./calisto/tomcat6-energy/energy.log.2016-01-05.gz ./calisto/tomcat6-energy/energy.log.2016-01-06.txt
and then run the command below for each line depend on the suffix. Output should be in another file. each output should have 2 lines space between them.
zcat users_energy.log.2016-03-20.gz | head -n5
This is my solution so far and I am not sure how should I complete it:
RAW_LOG_DIR=/var/cache/logs/recent_log.txt OUTPUT_DIR=/var/cache/logs/output for LOG in $RAW_LOG_DIR; do zcat -f ${RAW_LOG_DIR} | head -n5 > OUTPUT_DIR done
Would you please to help me to how can I differentiate between cat or zcat ,.. and how to complete my code?
Advertisement
Answer
I think you’re looking for something like this:
raw_log_dir=/var/cache/logs/recent_log.txt output_dir=/var/cache/logs/output i=0 while read -r line; do (( i > 0 )) && printf 'nn' i=$(( i + 1 )) if [[ $line = *.gz ]]; then zcat "$line" | head -n5 else head -n5 "$line" fi done < "$raw_log_dir" > "$output_dir"
Read each line of the file in $raw_log_dir
(always quote variables, read lines with while read
, not for
). If the line ends in .gz
, then use zcat
, else just use head
directly. Redirect the output of the loop to the other file. Note my use of lowercase variable names, which is considered good practice, as uppercase ones may clash with those used by the shell.
The first two lines of the loop add two blank lines before the output for every line after the first. On some shells you can do this more succinctly by using (( i++ > 0 )) && printf 'nn'
but ++
isn’t a standard feature so this way is more portable.
To check whether files exist before attempting to read them, you can add a line like this to the top of your loop:
[[ -f $line ]] || continue