Linux find skip directory

bash — excluding directory in «for file in $(find . )»

I have to do a script, which copy all the *.txt files from home directory to the newly created directory specified in the first argument of this script ($<1>). If the backup directory already exists, I want to skip it. I was trying the -prune excluding in find, but it doesn’t work for me. Finally I have made if statement in the loop, which also doesn’t work, and I don’t know why. Thank’s for help!! Here’s my code:

#!/bin/bash mkdir $ for file in $(find ~/ -name *.txt) do if [ ! -f ~/$/$file ] then cp -i -v $file -t ~/$ fi done 

3 Answers 3

#!/bin/bash [[ -n "$1" ]] || < echo >&2 'Give me an argument!'; exit 1; > destdir=$(readlink -m -- "$1") [[ "$destdir" == *\** ]] && < echo >&2 "Sorry, I'm in the stupid situation where the destination dir contains the \`*' character. I can't handle this."; exit 1; > mkdir -pv -- "$destdir" || < echo >&2 "Couldn't create directory \`$destdir'. Sorry."; exit 1; > find "$HOME" -path "$destdir" -prune -o \( -name '*.txt' -exec cp -iv -t "$destdir" -- <> \; \) 

Pro: Works with files that have spaces or funny symbols in their name (unlike yours) (except one stupid case, see Con below).

Con: As ormaaj pointed out in a comment, this might fail miserably if the name of your destination path contains the pattern character * . This case is safely taken into account, and the script exits gracefully if it ever happens.

Explanations.

  • Give an argument to that script. It can be absolute of relative to the current directory. readlink , with the -m option will take care to translate this to an absolute path: that’s the variable destdir .
  • The directory $destdir is created with its parents, if applicable.
  • In home directory, if we find $destdir directory, we prune this branch, otherwise, we look for all *.txt files and copy them to $destdir .
Читайте также:  Linux wget what is my ip

Once again, this script is 100% safe regarding file names with funny symbols: spaces, newline characters or hyphens, except for the pattern character * in the destination directory name, but that case is handled safely by a graceful exit, instead of potentially screwing up the files.

Источник

How to skip multiple directories when doing a find

I’ve written a find function that searches for a string in each file in a given path, while skipping a list of directory names that I don’t want searched. I’ve placed this script in my .bashrc file to be called like so:

findTEXTinFILES /path/to/search 'text-to-find' 
  • How do you skip multiple directories?
  • How do you skip directories with just a partial name, such as those that begin with ‘—‘ or ‘wp-‘?
  • Can you mix -name and -path criteria in the same script?
  • Is there something else I’ve missed?

My server is CENTOS 6.9 virtuozzo with the bash shell.

function findTEXTinFILES < find "$1" ! \( -name .bash_history -prune \ -o ! -path tmp -prune \ -o ! -path short -prune \ -o ! -path "*/_not_used/*" -prune \ -o ! -path backups -prune \ -o ! -path temp_logs -prune \ -o ! -name .cpan -prune \ -o ! -name .cpobjcache -prune \ -o ! -path files_to_compare -prune \ -o ! -path logs -prune \ -o ! -path mail -prune \ -o ! -path old -prune \ -o ! -path '--*' -prune \ -o ! -path 'wp-*' -prune \ -o ! -path '*copy*' -prune \) \ -o -name "*" \ -exec grep $2 -I --color -Hn '$3' '<>' 2>/dev/null \; > 

1 Answer 1

A find expression is composed primarily of tests and actions joined together with operators. It is evaluated in a standard short-circuiting manner — meaning the evaluation is stopped as soon as the result is known, without the need to evaluate all parts (e.g. true or anything is evaluated to true ).

Now note that -prune is an action that always returns true . It can act on the result of any test. Also note that the default operator is -a (and).

So, the simplest pruning example, to print all files except those under some path (e.g. wp-* in your example) looks like:

find . -path './wp-*' -prune -o -print 

For files matching the path starting with ./wp- , prune action is executed, meaning the result is true , and the right part of the OR operator can be ignored (i.e. file is not printed). Note here that -path matches relative path, in this case rooted at . , so we have to write ./wp-* instead of wp-* .

Читайте также:  Find program files linux

To prune two paths, simply extend:

find . -path './wp-*' -prune -o -path ./logs -prune -o -print 

Here: if first prune action is not executed (result false ), then a chance is given to the second, if that doesn’t prune neither (result false ), then -print action is executed. In case any -prune gets evaluated, -print doesn’t get a chance.

Applying this to your case:

find "$1" -name .bash_history -prune \ -o -path "$1/tmp" -prune \ -o -path "$1/short" -prune \ -o -path "$1/*/_not_used/*" -prune \ -o -path "$1/backups" -prune \ -o -path "$1/temp_logs" -prune \ -o -name "$1/.cpan" -prune \ -o -name "$1/.cpobjcache" -prune \ -o -path "$1/files_to_compare" -prune \ -o -path "$1/logs" -prune \ -o -path "$1/mail" -prune \ -o -path "$1/old" -prune \ -o -path "$1/--*" -prune \ -o -path "$1/wp-*" -prune \ -o -path "$1/*copy*" -prune \ -exec grep $2 -I --color -Hn '$3' '<>' 2>/dev/null \; 

To avoid writing $1 -dependent paths, you can cd «$1» and use f.e. find . . -path ./logs . .

Источник

How do I make «find» exclude the folder it searches in?

I would like to delete all the folders under the processing folder (the processing folder should never be deleted). The command is deleting the processing folder as well. How do I limit the script to delete only the folders under that folder?

3 Answers 3

The easiest way would be to just add -mindepth 1 , which will skip the first depth hierarchy and thus leave out your parent directory.

Also, you don’t need an extra -exec call to rm , you can just delete the folders directly if they’re empty.

find /var/www/html/content/processing -mindepth 1 -type d -mtime +1 -delete 
find /var/www/html/content/processing -mindepth 1 -type d -mtime +1 -exec rm -rf <> \; 

If you’re lazy you can also have a wildcard expanded. Since * doesn’t include the current directory by default (unless dotglob is set), you could also do:

find /var/www/html/content/processing/* -type d -mtime +1 -delete 

However, this would also not include hidden folders, again due to the dotglob option.

Читайте также:  Linux commands for ubuntu

Hi, I get «find: warning: you have specified the -mindepth option after a non-option argument -type, but options are not positional (-mindepth affects tests specified before it as well as those specified after it). Please specify options before other arguments. » and also «find: cannot delete `/folder/50d82faf0e09e’: Directory not empty»

Add mindepth before type then. To delete the directories when not empty you can stick with the rm approach you had originally.

The problem is that find returns the current directory (.) along with the other directories, so it deletes the processing folder as well as the subdirectories. A quick way to get around that would be to append the option

which stops find from outputting the current directory, and in turn stops it from being deleted.

That would work if you were running the command within the processing directory, so to allow for the fact that you are using an absolute path:

-not -name /var/www/html/content/processing 

And the whole command would be:

find /var/www/html/content/processing -type d -mtime +1 -not -name /var/www/html/content/processing -exec rm -rf <> \; 

The last command is wrong. -name refers to basename, it never matches anything with a slash. You probably need to use -path .

Already answered, still I would like to list another approach.

find /var/www/html/content/processing -mindepth 1 -maxdepth 1 -type d

This will exclude top directory (and also sub directories), and now you can apply whatever command that we want to apply over it.

>> Options:
-mindepth 1 : To exclude root directory
-maxdepth 1 : To avoid parsing sub directories. (For particular scenario as questioned, you don’t need this).
-type d : List only directory types. This option should come after mindepth maxdepth uses.

Источник

Оцените статью
Adblock
detector