LinuxQuestions.org
Visit the LQ Articles and Editorials section
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices

Reply
 
LinkBack Search this Thread
Old 08-08-2010, 02:42 AM   #1
jmark
LQ Newbie
 
Registered: Aug 2010
Posts: 4

Rep: Reputation: 0
remove directories that only contain .txt and .log files?


I'd like to remove all directories of a certain depth that don't contain .txt or .log files -- is this possible? So far I have:

find ~ -mindepth 3 -maxdepth 4 -type d -exec rm -r '{}' \;

Is it possible to add in "only if the directory doesn't contain .txt and/or .log files"? Or do I have to start learning perl to do that?

For example:

dir 1:
hello.txt
runme.sh

dir 2:
runme.sh
oct12.log

dir 3:
runme.sh

dir 4:
<empty>


It would delete directories 3 & 4
 
Old 08-08-2010, 03:26 AM   #2
r3sistance
Senior Member
 
Registered: Mar 2004
Location: UK
Distribution: CentOS 5.4, Mac OS 10.4 (tiger)
Posts: 1,005

Rep: Reputation: 79
As a quick method of finding out if a directory contains files that are not just .txt or .log... "ls -a | grep -v .txt | grep -v .log". there might be an easier way to do both in a single grep but -a is important since there might be hidden files to consider, however they may also be common hidden files, if you don't care to bother to check for them or of them then just do a normal ls with the grepping.

a very quick bash script I think would be

Directory = <some directory>
Filecheck = 'ls ${Directory} | grep -v .*\.txt$ | grep -v .*\.log$'
# more advanced version of the greps.. I am still unable to merge these into a single grep =/.

if [ ${Filecheck} = "" ]
then
rm ${Directory}
fi

however I only tentatively know bash scripting so this likely could use a lot of improvement, I am more of a c, php, vb, javascript, java... kinda man.

Last edited by r3sistance; 08-08-2010 at 03:35 AM.
 
Old 08-08-2010, 03:55 AM   #3
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371Reputation: 2371
@r3sistance:
Quote:
# more advanced version of the greps.. I am still unable to merge these into a single grep =/.
egrep -v "\.txt$|\.log$" or grep -Ev "\.txt$|\.log$"

The pipe character (|) separates the regular expressions.

Hope this helps.
 
1 members found this post helpful.
Old 08-08-2010, 04:06 AM   #4
r3sistance
Senior Member
 
Registered: Mar 2004
Location: UK
Distribution: CentOS 5.4, Mac OS 10.4 (tiger)
Posts: 1,005

Rep: Reputation: 79
Sure, I don't usually do fantastic things with grep myself... but always useful to know. I realize I made another mistake above.

should have been rmdir ${Directory} not rm${Directory} anyways.
 
Old 08-08-2010, 04:08 AM   #5
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946
You can also use -e to define multiple expressions.
Code:
egrep -v -e ".txt$" -e ".log$"
 
Old 08-08-2010, 04:15 AM   #6
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,191

Rep: Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784
How about a while loop:
Code:
while read dir
do
    [[ -n $(ls $dir/*{txt,log} &> /dev/null) ]] || echo rm -r $dir
done< <(find $HOME -mindepth 3 -maxdepth 4 -type d)
 
Old 08-08-2010, 04:47 AM   #7
jmark
LQ Newbie
 
Registered: Aug 2010
Posts: 4

Original Poster
Rep: Reputation: 0
Wow, that was quick!

I mishmashed everyone's ideas and this seems to work:

while read dir
do
Filecheck=$(ls ${dir} | egrep -e ".txt$" -e ".log$")
if [ -z ${Filecheck} ]
then
echo rm -r ${dir}
fi

done< <(find $HOME -mindepth 3 -maxdepth 4 -type d)




I tried to get this to work in the while loop:
[[ -n $(ls $dir/*{txt,log} &> /dev/null) ]] || echo rm -r $dir
It seemed to pick every directory though, and I don't understand the syntax enough to figure out what the problem was.

Thanks!

Last edited by jmark; 08-08-2010 at 04:48 AM.
 
Old 08-08-2010, 04:54 AM   #8
jmark
LQ Newbie
 
Registered: Aug 2010
Posts: 4

Original Poster
Rep: Reputation: 0
Doh, Filecheck=$(ls ${dir} | egrep -e ".txt$" -e ".log$") doesn't seem to work when dir has a space in it.
 
Old 08-08-2010, 05:09 AM   #9
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,191

Rep: Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784
So quote anything you need to preserve the space, ie "$dir"

The test I wrote had 2 issues (my bad) I redirected all input and should have only been stderror and used the wrong control

Try:
Code:
while read dir
do
    [[ -n $(ls "$dir/*{txt,log}" 2> /dev/null) ]] && echo rm -r "$dir"
done< <(find $HOME -mindepth 3 -maxdepth 4 -type d)
 
Old 08-08-2010, 05:33 AM   #10
jmark
LQ Newbie
 
Registered: Aug 2010
Posts: 4

Original Poster
Rep: Reputation: 0
Thanks -- I played around with putting quotes, but couldn't find the right place until your suggestion.

Code:
while read dir
do
    [[ -n $(ls "$dir/*{txt,log}" 2> /dev/null) ]] && echo rm -r "$dir"
done< <(find $HOME -mindepth 3 -maxdepth 4 -type d)
Doesn't print anything now -- I'll have to play around with it.



With the quote changes for directories containing spaces, the following works well, thanks!
(I had to subtract 1 from the depth arguments because of the ls in the while loop)

Code:
while read dir
do
Filecheck=$(ls "${dir}" | egrep -e ".txt$" -e ".log$")
if [ -z ${Filecheck} ]
then
echo rm -r "${dir}"
fi
   
done< <(find $HOME -mindepth 2 -maxdepth 3 -type d)

Last edited by jmark; 08-08-2010 at 05:36 AM.
 
Old 08-08-2010, 06:11 AM   #11
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,695
Blog Entries: 5

Rep: Reputation: 239Reputation: 239Reputation: 239
using shell expansion instead of calling ls

Code:
shopt -s nullglob
find ~ -mindepth 3 -maxdepth 4 -type d | while read -r DIR
do
  v=$(echo $DIR/*.txt $DIR/*.log)
  [[ -z $v ]] && rm -fr "$DIR" 
done
 
Old 08-09-2010, 12:18 AM   #12
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946
Quote:
Originally Posted by jmark View Post
Code:
ls "$dir/*{txt,log}"
Doesn't print anything now -- I'll have to play around with it.
Quoting protects all special characters(1), so your *, {, and } also become literal parts of the string here. So be careful to quote only the parts you need to protect, usually the variable and other literal strings, and not those characters the shell needs to process as commands.
Code:
ls "$dir"/*{txt,log}
(1) There's a difference between double and single quotes here. Double-quotes do not protect $, `, and \, which means you can still use variables, embedded commands, and escape sequences inside them. Single quotes, however, protect *everything* (except for another single quote, of course).

Correct quoting is a very important part of scripting; one small mistake can cost you many hours in debugging a large script. More on it here:
http://www.tldp.org/LDP/abs/html/quoting.html

Last edited by David the H.; 08-09-2010 at 12:20 AM. Reason: Corrected my own "quoting"
 
Old 08-09-2010, 12:34 AM   #13
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,191

Rep: Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784Reputation: 1784
Quote:
(I had to subtract 1 from the depth arguments because of the ls in the while loop)
Of course this change would need to be applied to my script as well ... otherwise it will not find the files.
 
Old 08-09-2010, 03:55 AM   #14
jthill
Member
 
Registered: Mar 2010
Distribution: Arch
Posts: 209

Rep: Reputation: 65
What happens if there are deeper subdirectories?

Code:
$ find . -mindepth 3 -iname '*.txt' -o -iname '*.log'
./a/b/c/d/testdata.txt
should directory c be removed or not? For safety, I'm guessing not, though I can read it both ways.


Let's ignore the possibility that directory names might contain newlines or single quotes.

Code:
$ find . -depth -mindepth 3 -type d \! -path '*/*/*/*/*' -o -type f \( -iname '*.txt' -o -iname '*.log' \) |
awk -F/ 'NF!=4 {k=1} NF==4 {if (k==0) print "rm -rf '\''" $0 "'\''";} NF==4 {k=0}'
will print out the rm commands for the depth 3 directories that contain no *.txt or *.log files anywhere underneath.

The find "-depth" option tells find to run depth-first, so it prints everything it finds in a directory before printing that directory. So I'm telling it to print any reason to keep a directory before printing that directory, then telling awk to print directories it doesn't see any reason to keep.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Copy the contents of a txt file to other txt files (with similar names) by cp command TheIndependentAquarius Linux - Newbie 7 07-03-2010 12:54 AM
[SOLVED] automate copying files to multiple directories with log file for admin simransab Linux - Newbie 6 10-01-2009 07:09 PM
remove log files suresh77 AIX 3 05-04-2006 10:10 AM
Remove files w/ extension txt recursively spiri Linux - General 4 12-14-2005 03:52 AM
How to remove files in /var/log /news and /mail keirobyn Linux - Newbie 6 07-19-2002 04:26 AM


All times are GMT -5. The time now is 04:05 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration