I am inexperienced with scripting and it continues to baffles me speechless
I wrote a script so that it counts the number of subset of files (with different prefix) in all subdirectories under the current directory so that
find ./ -type d -maxdepth 1 -mindepth 1 > list_of_dir.txt
find all subdirectories under the current directory and output the list to txt file
sed 's/^...//' <list_of_dir.txt >list_of_dir2.txt
edit the output file so that .//directory becomes directory
rm list_of_dir.txt
echo list of data > list_of_data.txt
for i in {1..$(wc -l < list_of_dir2.txt)}
do
echo "\n$(sed -n "$i"p list_of_dir2.txt)" >> list_of_data.txt
cd ./"$(sed -n "$i"p list_of_dir2.txt)"
ls *.jpeg | awk -F_ '{A[$1 FS $2]++} END {for (j in A) printf "%-20s%4d \n", j, A[j] >> "../list_of_data.txt"}'
cd ..
done
from each subdirectory in the txt file, output the directory name to file list_of_data, then cd into that directory, then count all the number of subset of files under different prefixes and output the result to list_of_data.txt
The problem is, if I run the script by typing ./scriptname.sh I get the error message
sed: 1: "{1..23}p": invalid command code .
sed: 1: "{1..23}p": invalid command code .
ls: cannot access *.jpeg: No such file or directory
but if I copy the content of the script and paste it in the terminal window it worked.
Thanks for your reply. As I said I am inexperienced I am sure there are much better way to write this.
Can you explain why the code works if I paste it in the terminal but it doesn't if I run it as a script?
As I explained above there are many subdirectories under the current directory. And inside each subdirectory there are a large number of files under different prefixes, like pict_1_1, pict_1_2, pict_2_1, pict_2_2, pict_2_3 etc etc etc
I want to count the number of file under each prefix from every subdirectory. with output like the sample output above into a txt file.
I would also appreciate it if you explain why you meant the extreme poor practice. I am keen to learn.
I think I am beginning to understand what the problem is. It seems the problem occurs with the sed command in the for loop. the error message
sed: 1: "{1..23}p": invalid command code .
stems from the fact that there are 23 folder in current directory and maybe I don't truely understand the mechanism of the for loop.....as
for i in {1..23}
then the
sed -n "$i"p list_of_dir2.txt
command tries to execute sed {1..23} all at the same time, hence the error.
During the for loop is it not like for i =1 then carries out the commands, then for i=2, carries out the command again etc etc until i=23? Why does sed trying to interpret i=1..23 all at the same time?
Still don't understand why the command runs when typed in terminal window but didn't when ran as script.
Well that is why I asked how your script starts: you seem to be using bash... the syntax you use will not be understood by bourne shell (default unless you specify as first line of your script...)
try to add as firstline of your script:
#!/sw64/bin/zsh
find ./ -type d -maxdepth 1 -mindepth 1 > list_of_dir.txt
sed 's/^...//' <list_of_dir.txt >list_of_dir2.txt
rm list_of_dir.txt
echo list of data > list_of_data.txt
no_of_dir=$(wc -l < list_of_dir2.txt)
for i in {1..$no_of_dir}
do
current_dir=$(sed -n "$i"p list_of_dir2.txt)
echo "\n"$current_dir >> list_of_data.txt
cd $current_dir
ls *.jpeg | awk -F_ '{A[$1 FS $2]++} END {for (j in A) printf "%-20s%4d \n", j, A[j] >> "../list_of_data.txt"}'
cd ..
done
OK, assuming that is the right zsh path, and if not there would be an error, is '{1..$no_of_dir}' a correct expanding string? Well, I have no zsh but the zsh doc says it is OK if the variable is expanded first. If not, you need an eval or something. Your use of it seems abuse (lose things in pile and then grope for them), why not just
while read current_dir;do ... done < list_of_dir2.txt
I wonder if its not something to do with your environment... You have something there that is missing in your scripts like PATH to a different find or sed etc... because -maxdepth is not standard in solaris so I can guess you are using gnu find, and so may also have another sed than the standard...
Have a check...
Yes, "while read" is a keeper, pipeline parallel and robust. Read can capture fields, and bash has "read -a simple_array_var_typedef_-a" so you do not even have to count or name them. I mostly use "while read a b c" where c gets the rest. I nevr use 'while read' with no vars, as I have to shift and type more for $REPLY.
One recent post noted that "for i in {1..999999999}" might make a command line too long, slowly, but "i=0; while (( ++i < 999999999 )) ; do ... done" has no such problems.