Checking if the files in a directory have a txt extension

    foreach file ($dir1/*)
        if ($file ~ *.txt) then
            echo "Skipping $file (is a txt file)"
        endif
    end

that should work right guys? :confused:

what about the simple command ?

ls -lrt *.txt | awk '{ print $8 " is txt file" }' 

i need to do something with these text files, that why i need a script

You can use :

foreach file (`ls`)
  echo $file | grep -q "\.txt"
  if ($status == 0 ) then
    echo "Skipping $file (is a txt file)"
  endif
end
for i in `ls *.txt`; do 
echo "$i is text file";  ## do what ever you need here.. $i is the file name (txt file)
done

You can use :

foreach file (`ls $dir1/*`)
  echo $file | grep -q "\.txt"
  if ($status == 0 ) then
    echo "Skipping $file (is a txt file)"
  endif
end

thx guys! i will try them out!

---------- Post updated at 05:18 AM ---------- Previous update was at 02:05 AM ----------

#!/bash/csh -f

foreach file ($argv/*)
  
  echo $file |grep -q "\.htm"     
  if($status == 0) then
  ./aa1 $file
  endif
  
end

ok guys i tried this, and it worked. but it works only for "argv" and argv is a argument, a directory i pass to the script.
how can i go through other directories inside the "argv" ?
like, if i call the the script,
script1 /home
i want it to check also all the folders in /home. isn't it supposed to do so with "-r" ?

in bash:

for file in $dir1/* ; do
if [[ "$file" =~ ".txt" ]]; then
echo "Skipping $file (is a txt file)"
fi
done
for f in $(find . -name "*.txt"); do
    echo Do something with ${f}.
done

Never, ever do that. 'for i in *.txt' is safer and cheaper. Using ls and command substitution means that it's impossible to handle filenames with IFS characters (by default, spaces, tabs, and newlines). Also, if there are very many *.txt files in the directory, a command line length limit imposed by the exec system call may prevent the operating system from successfully launching ls; this is not an issue with the shell pattern glob as it does not require a new process.

Please pass along the cluestick thwack when you see someone else doing the same :wink:

Regards,
Alister

Alister is correct that command substitution is expensive in terms of processing resources, but using a simple *.txt will not find the files in sub-directories. See my previous post. Unless you are dealing with thousands of files, the resource constraint should not be a problems.

While I did mention that the sh glob is "cheaper" (which I now regret), please note that my post is about correctness and robustness, not performance.

I wasn't referring to searching subdirectories, only that specific use of ls. It serves absolutely no purpose whatsoever and can only result in mishandled filenames. In such a case, where ls is being used to retrieve the filenames in directories (non-recursively), always use file expansion instead.

While we're here, your find solution is also unable to properly handle any filenames with IFS characters (though it's not constrained by a command length limit if there are very many *.txt files). It could be made to handle spaces and tabs correctly, though not newlines, if instead of using the find in a command substitution in a for loop's list, you piped the output of find into a while read loop.

One last point: Please don't misinterpret my intention. I realize that most of the time technically-limited solutions are more than adequate; I use them all the time myself. I simply highlight the limitations so that anyone who is not aware of them will learn.

Regards,
Alister

@alister, Understood.

The statement I provided should handle special characters in the find and for loop statements. How the files are processed after finding them is up to the code within the for loop. File names should not include new line characters...at least I have yet to encounter one. If you have a suggestion for dealing with such an occurrence, please include it so we can all learn from it.

Thanks.

im trying this in csh but it doesn't seem to work.

btw
im checking the second parameter, like this

if($argv[2] == "-r") then

search in all the sub-folders of that folder

endif

If by special characters you mean IFS characters, it will not, and it cannot be made to do so. The shell splits the results of the find command on IFS characters (by default, space, tab, and newline). If a filename contains any of those characters, it is broken up into words and each word is fed to the loop one at a time. The only way to prevent the shell from field splitting the results of a command substitution is to double quote it, but that would always result in one word, and a loop that will only execute once (which isn't much of a loop, ;)).

An illustrative example using spaces, which aren't that uncommon:

$ touch 'i have spaces.txt'
$ ls 
i have spaces.txt
$ for f in $(find . -name "*.txt"); do echo "$f"; done
./i
have
spaces.txt

Note how the filename was mangled because it was split into three words. A better approach:

$ find . -name "*.txt" | while IFS= read -r f; do echo "$f"; done
./i have spaces.txt

That will handle everything except newlines in filenames, since find injects newlines into its output stream as a delimiter. While I agree that people using newlines in filenames deserve all the pain that a posix-compliant environment can throw at them, if such names need to be handled, the only posix-compliant solution I know of for a situation that requires recursion is (where myscript.sh is a shell script that does whatever needs doing with the filenames passed to it via positional parameters):

find . -name "*.txt" -exec myscript.sh {} +

Although it's not posix-compliant, the following is likely supported:

find . -name "*.txt" -print0 | xargs -0 myscript.sh

myscript.sh can then safely loop through the filenames, even if they contain a newline, using the following for loop:

for f; do
    ...process "$f"....
done

(when the for loop's list is absent, it defaults to "$@")

Regards,
Alister

---------- Post updated at 02:43 PM ---------- Previous update was at 02:28 PM ----------

Apologies, pantelis. It seems that your thread took a detour into bourne sh land, in no small part because of my comments. If you can switch away from csh to sh, you'll find that there are MANY more people able to provide assistance.

Regards and best of luck,
Alister

@alister, thanks for clarifying. I guess I generally use camelBack naming convention so I have not come across this before. I think I also assumed (I know, my bad) that the for loop would only use one delimiter. Since the find command would return multiple files, the new line would be the file name delimiter and the spaces would be used as part of the name.