Komal Rathi
Komal Rathi

Reputation: 4274

script to traverse through directories and subdirectories to list files

#!/bin/bash
#script to loop through directories to merge files

mydir=/data/
files="/data/*"

for f in $files
do
    if[ -d "$f" ]
    then
            for ff in $f/*
            do
                    echo "Processing $ff"
            done
    else
            echo "Processing $f"
    fi
done

I have the above code to go through directories and sub-directories and list all the files. I am getting the error: syntax error near unexpected token `then'

What am I doing wrong here?

Upvotes: 3

Views: 25862

Answers (3)

Mike Q
Mike Q

Reputation: 7327

Here's a function that does what you ask, you pass it a folder see the call at the bottom func_process_folder_set "/folder".

    # --- -------------------------------- --- #
    # FUNC:  Process a folder of files
    # --- -------------------------------- --- #
    func_process_folder_set(){

        FOLDER="${1}"

        while read -rd $'\0' file; do

            fileext=${file##*.}  # -- get the .ext of file
            case ${fileext,,}    # -- make ext lowercase for checking in case statement
            echo "FILE: $file"   # -- print the file  (always use " " to handle file spaces)

        done < <(find  ${FOLDER} -type f -maxdepth 20 -name '*.*' -print0)

    }

    # -- call the function above with this:
    func_process_folder_set "/some/folder"

Upvotes: 0

John Kugelman
John Kugelman

Reputation: 361575

if [ -d "$f" ]
  ^

There needs to be a space between if and [. If you don't have a space, bash thinks you're trying to execute a command named if[.


files="/data/*"
for f in $files

Also know that this won't work. To store a wildcard expansion in a variable like that you need to use an array. The syntax is a bit hairier...

files=(/data/*)
for f in "${files[@]}"

Or you could write the wildcard inline the way you do with the inner loop. That would work fine.

for f in "$mydir"/*

For what it's worth, you could use find to recurse through all files and sub-directories recursively.

find /data/ -type f -print0 | while read -d $'\0' file; do
    echo "Processing $file"
done

-type f matches files only. -print0 combined with -d $'\0' is a way to be extra careful with file names containing characters like spaces, tabs, and even newlines. It is legal to have these characters in file names so I like to write my scripts in a way that can handle them.

Note that this will recurse deeper than just sub-directories. It'll go all the way down. If that's not what you want, add -maxdepth 2.

Upvotes: 10

John Ledbetter
John Ledbetter

Reputation: 14173

As an alternative, you could probably replace this entire loop with something like

# find all files either in /data or /data/subdir
find  /data -type f -maxdepth 2 | while read file; do
  echo $file;
end

Upvotes: 4

Related Questions