Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shell script to traverse directories

Tags:

bash

I'm working on a project that requires batch processing of a large number of image files. To make things easier, I've written a script that will create n directories and move m files to them based on user input.

My issue is to now understand directory traversal via shell script.

I've added this snippet at the end of the sort script described above

dirlist=$(find $1 -mindepth 1 -maxdepth 1 -type d)

for dir in $dirlist
do
  cd $dir
  echo $dir
  ls
done

When I ran it inside a Pano2 folder, whcih contains two inner folders, I always got an error

./dirTravel: line 9: cd: Pano2/05-15-2012-2: No such file or directory

However, after that, I get the file listing from specified directory.

What is the reason behind the warning? If I add cd ../ after ls I get the listing of the folders inside Pano2/, but not the files themselves.

like image 380
Jason Avatar asked Dec 20 '22 21:12

Jason


2 Answers

I recommend using a sub-shell to switch directories:

dirlist=$(find $1 -mindepth 1 -maxdepth 1 -type d)

for dir in $dirlist
do
  (
  cd $dir
  echo $dir
  ls
  )
done

The code inside the sub-shell won't affect the parent shell, so it can change directory anywhere without giving you any issues about 'how to get back'.

This comes with the standard caveat that the whole process is fraught if your directory names can contain spaces, newlines or other unexpected and awkward characters. If you keep with the portable filename character set ([-_.A-Za-z0-9]) you won't run into problems as written.

like image 178
Jonathan Leffler Avatar answered Dec 31 '22 01:12

Jonathan Leffler


My guess is that you're going in two levels deep, but only coming back up one level. Try adding a cd ../.. after the ls, or use pushd and popd instead.

For example:

for dir in $dirlist
do
  pushd $dir
  echo $dir
  ls
  popd
done

As @shellter points out, if those directories have spaces, then something like this might work better:

find $1 -mindepth 1 -maxdepth 1 -type d | while read -r dir
do
  pushd "$dir"  # note the quotes, which encapsulate whitespace
  echo $dir
  ls
  popd
done
like image 36
Nate Kohl Avatar answered Dec 31 '22 00:12

Nate Kohl