3

I am trying to get files having size greater than 1k and with an txt extension my code is as follows :

files=$(find foldername -size +1k -name \*.txt -exec {} \;)

for item in $files
do 
echo $item
done

But I am getting unexpected output as given below. Please help !!!

DEST/sample - Copy - Copy.txt: line 1: Hello: command not found
DEST/sample - Copy - Copy.txt: line 2: This: command not found
DEST/sample - Copy - Copy.txt: line 3: In: command not found
DEST/sample - Copy - Copy.txt: line 4: $'\r': command not found
DEST/sample - Copy - Copy.txt: line 5: User: command not found
DEST/sample - Copy - Copy.txt: line 6: -s: command not found
DEST/sample - Copy - Copy.txt: line 7: -d: command not found
DEST/sample - Copy - Copy.txt: line 8: -t: command not found
DEST/sample - Copy - Copy.txt: line 9: $'\r': command not found
DEST/sample - Copy - Copy.txt: line 10: $'\r': command not found
DEST/sample - Copy - Copy.txt: line 11: Hello: command not found
DEST/sample - Copy - Copy.txt: line 12: This: command not found
DEST/sample - Copy - Copy.txt: line 13: In: command not found
DEST/sample - Copy - Copy.txt: line 14: $'\r': command not found
DEST/sample - Copy - Copy.txt: line 15: User: command not found
DEST/sample - Copy - Copy.txt: line 16: -s: command not found
DEST/sample - Copy - Copy.txt: line 17: -d: command not found
DEST/sample - Copy - Copy.txt: line 18: -t: command not found
DEST/sample - Copy - Copy.txt: line 19: $'\r': command not found
DEST/sample - Copy - Copy.txt: line 20: Hello: command not found
DEST/sample - Copy - Copy.txt: line 21: This: command not found
DEST/sample - Copy - Copy.txt: line 22: In: command not found
DEST/sample - Copy - Copy.txt: line 23: $'\r': command not found
DEST/sample - Copy - Copy.txt: line 24: User: command not found
DEST/sample - Copy - Copy.txt: line 25: -s: command not found
DEST/sample - Copy - Copy.txt: line 26: -d: command not found
DEST/sample - Copy - Copy.txt: line 27: -t: command not found
DEST/sample - Copy.txt: line 1: Hello: command not found
DEST/sample - Copy.txt: line 2: This: command not found
DEST/sample - Copy.txt: line 3: In: command not found
DEST/sample - Copy.txt: line 4: $'\r': command not found
DEST/sample - Copy.txt: line 5: User: command not found
DEST/sample - Copy.txt: line 6: -s: command not found
DEST/sample - Copy.txt: line 7: -d: command not found
DEST/sample - Copy.txt: line 8: -t: command not found
DEST/sample - Copy.txt: line 9: $'\r': command not found
DEST/sample - Copy.txt: line 10: $'\r': command not found
DEST/sample - Copy.txt: line 11: Hello: command not found
DEST/sample - Copy.txt: line 12: This: command not found
DEST/sample - Copy.txt: line 13: In: command not found
DEST/sample - Copy.txt: line 14: $'\r': command not found
DEST/sample - Copy.txt: line 15: User: command not found
DEST/sample - Copy.txt: line 16: -s: command not found
DEST/sample - Copy.txt: line 17: -d: command not found
DEST/sample - Copy.txt: line 18: -t: command not found
DEST/sample - Copy.txt: line 19: $'\r': command not found
DEST/sample - Copy.txt: line 20: Hello: command not found
DEST/sample - Copy.txt: line 21: This: command not found
DEST/sample - Copy.txt: line 22: In: command not found
DEST/sample - Copy.txt: line 23: $'\r': command not found
DEST/sample - Copy.txt: line 24: User: command not found
DEST/sample - Copy.txt: line 25: -s: command not found
DEST/sample - Copy.txt: line 26: -d: command not found
DEST/sample - Copy.txt: line 27: -t: command not found
Thomas Dickey
  • 76,765

3 Answers3

1

The apparent problem: the find-command is doing an -exec {}, which attempts to execute each file which was found (the source of most of the error messages). Perhaps you meant just -print, e.g.,

files=$(find foldername -size +1k -name \*.txt -print)

You will also get into trouble with the list, if it happens to find files with blanks in their names — but you will see that once you find the files correctly.

There are several ways to do this; here's one making little change to your script:

find foldername -size +1k -name \*.txt -print | \
while IFS= read -r item
do 
echo "$item"
done
Thomas Dickey
  • 76,765
  • Now I am not getting an error but unfortunately there is a space in my file name due to which for loop I am getting in correct result. I have only 2 files in my folder which matches the condition but I am getting 8 result due to spaces in file name – BASEER HAIDER JAFRI Feb 19 '16 at 01:55
  • My file names are : sample - Copy - Copy.txt and sample - Copy.txt and I am getting following result : DEST/sample ; - ; Copy ; - ; Copy.txt ; DEST/sample ; - ; Copy.txt – BASEER HAIDER JAFRI Feb 19 '16 at 01:58
0

Assuming -exec is to what you mean to do. (The option -exec executes a file not read it)

The simple solution to print the filenames that match find options is:

find foldername -size +1k -name \*.txt -print

If you need the names to be assigned to a variable, you need more. To be able to deal with spaces in file names that result from the command find, the option -print0 is the usual solution:

find foldername -size +1k -name \*.txt -print0

However, to be able to read the results into a bash variable, is not easy.
There is a long explanation in this excellent Greg's wiki page

#!/bin/bash
unset a
while IFS= read -r -d $'\0' file; do
    a+=( "$file" )        # or however you want to process each file
done < <(find foldername -size +1k -name \*.txt -print0)

printf 'filename=%s\n' "${a[@]}"
0

With -exec {} \;, you're telling find to execute each of the files that it finds as a command. It seems that you meant to print out the file names, so say that: -print. But that breaks if the file names contain whitespace. It's generally a bad idea to parse the output of ls or find; only do it if you're absolutely sure that it's impossible for the file names to contain whitespace or other special characters.

The safe way to act on find results is to make find trigger the action. If you need to use some shell constructs (multiple commands, if, variable expansion, pipes, etc.), invoke a shell. Pass the file name as an argument to that shell.

find … -exec sh -c '
  echo "$0"
' {} \;

You can make this faster by invoking a shell for a batch of files instead of one for each file.

find … -exec sh -c '
  for item do
    echo "$item"
  done
' sh {} +