unable to process files of a directory in for loop in linux
i have directory that has 2 sub-directories and that again has few sub-directory and they have some files. I need to rename all the files to append an html extension to the filenames. the directory structure looks like this
main-directory
sub-directory
sub-directory
sub-directory
file1
file2
and so on to lot of files
now i could not use something like this
for file in main-directory/*
do
if [ -f "$file" ]
then `mv "$file" "$file.html"`
fi
done
because the for loop wont use the path recursively. so i used something like this
for file in `ls -1R main-directory` // -1 for showing file and directory names separat开发者_如何转开发ed by new lines and -R for recursive travel
do
if [ -f "$file" ]
then `mv "$file" "$file.html"`
fi
done
the above code is not able to rename files. to check whether the line
for file in `ls -1R main-directory`
is working i wrote something like this
for file in `ls -1R main-directory`
do
if [ -f "$file" ]
echo $file
done
this doesn't show anything. what can be wrong?
you can use find and look into of type file and then -exec to change all the file and then appending the .html.
find main-directory -type f -exec mv -v '{}' '{}'.html \;
In your first for
loop, the mv
command should not be in back-ticks.
In your second for
loop, the if-statement has incorrect syntax. There is no then
or fi
. It should be:
for file in `ls -1R main-directory`
do
if [ -f "$file" ]
then
echo $file
fi
done
But even then, this won't work because ls -1R main-directory
gives you just the file names, not the absolute paths to the file. Move your echo outside the if-statement to test:
for file in `ls -1R main-directory`
do
echo $file
done
Therefor ls -1R main-directory
is not a good way to get all files in the current directory. Use find . -type f
instead.
For some reason, I can never remember the find ... -exec
syntax off the top of my head with the {}
and the \;
. Instead, I've fallen into the habit of just using a loop fed from find:
find main-directory -type f | while read file
do
mv "$file" "$file.html"
done
find
outputs each file to stdout and the read file
will consume one line at a time and set the contents of that line to the $file
environment variable. You can then use that anywhere in the body of your loop.
I use this approach to solve lots of little problems like this where I need to loop over a bunch of output and do something useful. Because it is more versatile, I use it more than the esoteric find ... -exec {} \;
approach.
Another trick is to prepend you command with echo
to do a quick sanity check before doing potentially damaging things to your system:
find find main-directory -type f | while read file
do
echo mv "$file" "$file.html"
done
here is the answer to my question. people responded by 1 liners which are a neat approach but i didnt get much out of those 1 liners so here is something that i wanted
IFS=$'\n' // this is for setting field separator to new line because the default is whitespace
dir=main-directory
for file in `ls -1R main-directory | sed 's/:$//'` // -1 for showing file and directory names separated by new lines and -R for recursive travel
do
if [ -f "$dir/$file" ]
then `mv "$dir/$file" "$dir/$file.html"`
elif [ -d "$file" ]
then dir=$file
fi
done
here the sed 's/:$//'
detects a :
at the end of line and removes it. this was one of the things that prevented my code to run because whenever ls -1R main-directory
detected a directory it appended a :
at the end
精彩评论