I cant make the following check to work
for file in `ls -R .`
do
if [-f $file] ......
The fact is that I want this check to match when it finds a file.gz
(gzip
compressed file) and it is not working.
Perhaps if you specified what "it is not working" means, we could help you better.
Anyway, if the output you get is "[-f command not found" then you have to put a space between [ and the inside (/usr/bin/[
is a full featured command):
if [ -f $file ] ...
but please be aware that the file might contain spaces or other strange characters, so as the very minimum I'd suggest putting quotes around "$file":
if [ -f "$file" ] ...
and even better, do not parse ls -R .
but use find .
instead
[ -f "$file" ]
will also return true for symlinks to regular files (as opposed to find
's -type f
for instance).
Commented
Oct 8, 2015 at 15:10
You do not want to parse ls
output. If you want a list of all .gz
files under a folder and do something to each result, the following is a better idea if you're using bash
or zsh
and your find
supports the -iname
and -print0
predicate (like on GNU, Solaris 11 or some BSD systems):
while IFS= read -r -d $'\0' file; do
echo "found a .gz: $file"
done < <(find . -type f -iname "*.gz" -print0)
find
's -type f
will not include symlinks to regular files (contrary to [ -f
). Use -xtype f
(GNU specific though) to include symlinks to regular files (well symlinks which you can tell eventually resolve to regular files, like symlinks to symlinks to regular files).
Commented
Oct 8, 2015 at 15:12
You have three problems.
One problem is that you need whitespace around the [ … ]
builtin.
[ -f $file ]
Another problem is that the output of ls -R
is pretty useless. ls -R
displays file names without the directory part, so unless you do some relatively heavy parsing of the output, you can't use it. The right tool to traverse directories recursively is find
, which has a different syntax.
The third problem is that you're missing double quotes around variable substitutions. This doesn't completely break the script, only if you encounter file names containing whitespace or \[*?
. Dealing with these file names is trivial as long as you remember to always use double quotes around variable and command substitutions: "$file"
, "$(mycommand)"
. For more information, see Why does my shell script choke on whitespace or other special characters?
find . -exec sh -c '
if [ "$0" ] …
' {} \;
Note that you can use find -type f
to only execute a command (or print out) on regular files, or (on Linux) find -xtype f
to also include symbolic links to regular files.
I know it's not quite what you asked, but it's common on Unix.
Have you considered perl? Because it lets you grep
based on all sorts of clever conditions.
E.g.
#!/usr/bin/env perl
use strict;
use warnings;
foreach my $file ( grep { -f } glob ( "*" ) ) {
print "$file is a file\n";
}
grep
iterates the list that glob
returns (expands as you would expect in a shell command) and then runs a -f
test on each, filtering the list accordingly.
You can also compound these tests in all sorts of arbitrary ways (like grabbing values from stat
etc.)
The reason I'm suggesting it is because it doesn't suffer any interpolation/expansion issues where parsing ls
might.
You can use the find
command like so:
for file in $(find . -type f -iname "*.gz")
do
#now if is not needed
...
done
This will save you from testing for file inside the loop.
need to use spaces
for i in `ls -R .`; do if [ $i == "file.gz" ]; then echo $i; fi; done
find . -type f -name file.gz
and work with its output?