Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looping through directories in Bash

I require the script to cd to a directory, then delete all but a few files in sub-directories—but leave the folders alone. Would it help to use switch/cases for each file I need to preserve?

Ideally, I think it should keep searching for further sub-dirs, instead of me having nested loops which only search down two levels.

Another problem is that it skips folders with spaces (though this isn’t an issue with the volumes that the script will run, for now).

Here’s my code:

for i in /Users/YourName/Desktop/Test/* ; do
  if [ -d "$i" ]; then
    cd $i

    for j in "$i"/* ; do
      if [ -d "$j" ]; then
        cd $j

        for k in $(ls *); do
          if [ ! $k == "watch.log" ]; then
            echo $k
            rm -rf $k
          fi
        done

      fi
    done

  fi
done
like image 259
infmz Avatar asked Apr 14 '11 14:04

infmz


People also ask

How do I loop a directory in Bash?

The syntax to loop through each file individually in a loop is: create a variable (f for file, for example). Then define the data set you want the variable to cycle through. In this case, cycle through all files in the current directory using the * wildcard character (the * wildcard matches everything).

How do you loop a directory in Linux?

We use a standard wildcard glob pattern '*' which matches all files. By adding a '/' afterward, we'll match only directories. Then, we assign each directory to the value of a variable dir. In our simple example, we then execute the echo command between do and done to simply output the value of the variable dir.

How do I traverse a directory in Unix?

This can be easily achieved by mixing find , xargs , sed (or other file modification command). This will filter all files with file extension . properties . The xargs command will feed the file path generated by find command into the sed command.


2 Answers

You should use find :

for i in $(find . -type d)
do
    do_stuff "$i"
done

If you really have a lot of directories, you can pipe the output of find into a while read loop, but it makes coding harder as the loop is in another process.

About spaces, be sure to quote the variable containing the directory name. That should allow you to handle directories with spaces in their names fine.

like image 127
static_rtti Avatar answered Oct 22 '22 13:10

static_rtti


How about this?

$ find /Users/YourName/Desktop/Test -type f -maxdepth 2 -not -name watch.log -delete


Explanation

  • -type: look for files only
  • -maxdepth: go down two levels at most
  • -not -name (combo): exclude watch.log from the search
  • -delete: deletes files


Recommendation

Try out the above command without the -delete flag first. That will print out a list of files that would have been deleted.

Once you’re happy with the list, add -delete back to the command.

like image 25
Hai Vu Avatar answered Oct 22 '22 12:10

Hai Vu