1

I am trying to write a simple bash script that displays the contents of files.

#!/bin/bash

echo 'Input the path of a file or directory...'
read File

if [ -e $File ] && [ -f $File ] && [ -r $File ]
    then
    echo 'Displaying the contents of the file '$File
    cat $File


elif [ -d $File ] && [ -r $File ]
then
echo 'Displaying the contents of the directory '$File       
    for FILE in `ls -R $File`
        do
               cd $File/$FILE
               echo 'Displaying the contents of the file '$FILE
               cat $FILE
        done

else 
echo 'Oops... Cannot read file or directory !'
fi

The user should input a file or directory path. If the user inputs a file the program displays it with cat. If the user inputs a directory it should display the content of all files including those in the subdirectories. That part of the program doesn't work very well. I would like to get a result that doens't display errors like 'No such file or directory' but only the content of files. Can you help me ? Thanks in advance.

buster
  • 167
  • 1
  • 5
  • 11
  • 1
    Never use `for i in $(command)` . See this answer for more details : http://stackoverflow.com/questions/19606864/ffmpeg-in-a-bash-pipe/19607361#19607361 Otherwise, I think that the best solution is to use `find` as described in some answer of this thread. – Idriss Neumann Oct 28 '13 at 21:20

3 Answers3

6

ls -R is the wrong tool to find all files in all subdirectories. find is a much better choice:

echo "displaying all files under $File"
find "$File" -type f -printf "Displaying contents of %p\n" -exec cat {} \;
evil otto
  • 10,348
  • 25
  • 38
3

You can print all files in the current directory just doing

for f in * do
    cat $f;
done
LeartS
  • 2,866
  • 2
  • 25
  • 45
  • Yes but in the for loop he can add other commands (like the "debug" echo he has) easily. I just gave him the structure. Why wrong? – LeartS Oct 28 '13 at 16:47
  • You are correct the loop allows more flexibility. The main issue is a `for` loop is the wrong approach. The OP uses `ls -R` which clearly means subdirectories are expected. Neither his loop nor yours handle this case properly. `find`is the way to go. – jlliagre Oct 28 '13 at 16:55
  • You can do recursive with `shopt -s nullglob globstar; for subdir in **/*/` but then it gets tedious to separate out file and directories. `find` is certainly easier if you just want to cat files. – glenn jackman Oct 28 '13 at 17:30
2

the find command will save you a lot of the logic:

#!/bin/bash 

echo 'Input the path of a file or directory...'
read File
DirName="."

if  echo $File | grep '/' ;  then
  DirName=$(dirname $File)
  File=$(basename $File)
fi

find "$DirName" -type f -name "$File" -exec cat {} \;
find "$DirName" -type d -name "$File" -exec ls {} 

The first find will look for all 'regular' (-type f) files name $File and cat them The second find will look for all 'directories' (-type d) and list them.

If they do not find any then the -exec portion will not execute. The grep will split the path is there is a slash in there.

SilverCode
  • 189
  • 4
  • Thanks for your response ! When I try to run your script I get an error ''find: warning: Unix filenames usually don't contain slashes...''. – buster Oct 28 '13 at 17:23
  • to get around that you can split the name using basename and dirname e.g. find $(dirname $File) -name "$(basename $File)" – SilverCode Oct 28 '13 at 21:58