Find file with extension and excluding directory

Hi,
I have an inquiry on how do I use the find command in Solaris Unix to find some file ends with extension : txt, err in the root directory with modified date of 30days and this find command will also need to exclude b directory and its subdirectory. All the files from the above find criteria will then move the files into c folder.

I have the below scripts but there is nothing being moved over to c folder even thought there are files existed in the root directory. Appreciate any help.

find . -name "*.txt" -o -name "*.err" -a -mtime -30 -a ! -type d -name "./b" -exec mv {} "./c" \;
find ./ -type f -regex '.*\.\(txt\|err\)' ... -not -path "./b/*"

Hi nezabudka,
Note that most Solaris systems don't have the -regex , -path , and -not primaries.

Hi snowfrost88,
The find command that you're using has two groups of primaries separated by a logical OR operator ( -o ). The first group of primaries is just -name "*.txt" . This group essentially finds all files with names ending with .txt and ignores them. The second group finds all files with names ending with .err that have been modified in the last 30 days that are not directories and that have the name ./b and moves all files that meet all of those requirements to the file named ./c (which we hope, but have not verified, is a file of type directory). Since no filename can ever contain a <slash> character, no filename can ever be selected by the -name ./b primary (and, therefore, no files will ever be moved by this command).

In addition to the problem noted above, I assume that what you're really trying to do is to move all files that have been modified within the last 30 days that either have a name ending in .txt or ending in .err that are not located in or under a directory named either b or c into the directory named c without duplicating any of the file hierarchy structure into the directory c . If that assumption is correct, you probably want something more like:

find . \( -type d \( -name b -o -name c \) -prune \) -o \( -type f -mtime -30 \( -name '*.txt' -o -name '*.err' \) -exec mv {} c/ \; \)

Note the sets of \( and \) grouping operators to alter the precedence the logical OR operators and the -prune primary to ignore all files under directories named b or c when selecting regular files with the extensions .txt and .err .

1 Like

Hi Don Cragun,
I do not want to find those files in b folder and its sub directory. I have alot of sub directories in b folder . How do I exclude from b folder as the parent? I am not able to list down all the folder in the command.

find . \( -type d \( -name b -o -name c \) -prune \) -o \( -type f -mtime -30 \( -name '.txt' -o -name '.err' \) -exec mv {} c/ \; \)

The \( -type d \( -name b -o -name c \) -prune \) in the code I suggested excludes everything in and under directories named b and c from being selected to be moved. (I exclude c because that is where you are moving all of your selected files and there is no need to move files from directory c to directory c , is there?)

Note also that if you have directories x , y , and z in the current directory and files with pathnames x/a.txt , y/a.txt , and z/a.txt that the code you have requested will effectively randomly delete two of those files and move the third to have the new pathname c/a.txt . And, in the above scenario, if there was a file with the pathname c/a.txt before the code you requested is run, that file will also be overwritten (i.e., destroyed).

2 Likes

For testing put an echo before the mv command!
The -o is a logical OR, read "otherwise".
The -a is default; you can put it for clarity (if there is no -o of course): find . -type f -a -print is identical with find . -type f -print