Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I am making a script to simplify my daily tasks. Everyday, I have to grep for a few things inside a company server. It was okay, however, now, they have segregated each object into sub directories. I am looking for a solution in which my existing shell script will execute repeatedly into each sub directory inside a certain directory. How do I do this? I am quite new to Ubuntu and still learning the ropes.

Here's my script:

#!/bin/bash

#fetch start time of uut
grep -i "01_node_setup" his_file | tail -1 >> /home/xtee/sst-logs.out

#check if sysconfig.out exists
if [ -f sysconfig.out];
then
    grep -A 1 "Drive Model" sysconfig.out | tail -1 >> /home/xtee/sst-logs.out
else
    grep -m 1 "Pair0 DIMM0" node0/trans_file_prev/*setupsys* | tail -1 >> /home/xtee/sst-logs.out
fi

Basically I want to run this script to execute on all the existing sub directories of a certain directory. What do I do? Thanks!

share|improve this question
    
Do the subdirectories have spaces in their names? Something simple you could do is for dir in $(ls); do ...; done, but it'll only work if names don't have spaces. –  Mark Paskal Aug 2 '12 at 10:07
    
Hi @MarkPaskal, no the subdirectories do not have spaces. Thanks! Will try this. :) Can this be done if let's say I just want to traverse just one sub directory deep? –  JudeJitsu Aug 2 '12 at 10:11
    
@JudeJitsu edited my answer, should work for all dirs even with spaces. –  Bruno Pereira Aug 2 '12 at 11:33
    
IIRC grep has a recursive flag? you could have grepped * with that flag and it would work? –  jackweirdy Aug 2 '12 at 16:13
1  
@Mark: You should never parse the output of ls. It's impossible to do so in a way that's guaranteed to work in all cases, and the proper way is simpler anyway. Try this: for file in *; do ...; done –  Scott Severance Aug 2 '12 at 23:32

3 Answers 3

up vote 0 down vote accepted

This should more or less do the trick. I am assuming that the 'node0' dir will be within the subdirectories if 'sysconfig.out' is not and that 'his_file' is also in the subdirectories.

#!/bin/bash
MainDir=/path/to/dir/containing/subdirs
# cd into dir
cd $MainDir

for dir in *; do

#fetch start time of uut
grep -i "01_node_setup" $dir/his_file | tail -1 >> /home/xtee/sst-logs.out

#check if sysconfig.out exists
if [ -f $dir/sysconfig.out];
then
    grep -A 1 "Drive Model" $dir/sysconfig.out | tail -1 >> /home/xtee/sst-logs.out
else
    grep -m 1 "Pair0 DIMM0" $dir/node0/trans_file_prev/*setupsys* | tail -1 >> /home/xtee/sst-logs.out
fi

done

#cd back to where we started
cd $OLDPWD
share|improve this answer
1  
Thanks Mark! Will also try this out! –  JudeJitsu Aug 2 '12 at 10:36
    
Okay, this worked but when I run the script, it displays [: 19: missing ] and the sst-logs.out file displays binary file /sub/directory/ as opposed to adding the output of the grep. –  JudeJitsu Aug 2 '12 at 10:53
1  
Never use ls to iterate files. Please see mywiki.wooledge.org/BashPitfalls –  geirha Aug 2 '12 at 16:07
1  
Also, you should surround variable expansions with double quotes, in case their values contain spaces or other "special" characters. E.g., "$foo", not $foo. –  Scott Severance Aug 2 '12 at 23:46
    
Using ls with a for loop to iterate files doesn't work if you quote the list of items to loop through. I understand that this method sucks (mainly because filenames with spaces wont work at all) but in this case it was known that the output of ls would not contain folder names with spaces. Thanks for your link @geirha –  Mark Paskal Aug 3 '12 at 2:51

You can iterate subdirs with a for-loop like this

#!/usr/bin/env bash

for dir in /the/path/*/; do
    awk 'tolower($0) ~ /01_node_setup/{line=$0} END{print line}' "$dir/his_file"

    if [[ -f "$dir/sysconfig.out" ]]; then
        awk '/Drive Model/{getline line} END{print line}' "$dir/sysconfig.out"
    else
        awk '/Pair0 DIMM0/{print;exit}' "$dir/node0/trans_file_prev"/*setupsys*
    fi
done >> /home/xtee/sst-logs.out

I changed your greps into awks that should be more portable. I believe they should produce the same output. The important parts are the quotes around the paths.

share|improve this answer
    
Great! Thanks for sharing some scrip fu skills! ;) (I cleaned all the comments here, hope that is ok) –  Bruno Pereira Aug 3 '12 at 13:38

An easier, though less elegant, way to iterate subdirectories is this:

base="/something"

iterator() {
  local dir="$1"
  local i=
  for i in "$dir"/*; do
    if [[ -d "$i" ]]; then
      iterator "$dir/$i"
    else
      # do something with this file
    fi
  done
}

iterator "$base"
share|improve this answer
    
You're missing a glob there –  geirha Aug 3 '12 at 6:06
    
Thanks for catching that. Fixed. –  Scott Severance Aug 3 '12 at 12:23

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.