开发者

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜