# Find & move script?



## snet2 (Mar 21, 2019)

I need help making a script to find and move and cannot seem to get it to work

Example
`find /mnt/SAN-01/Word\ Documents/ -name 'STUFF' -exec mv -R /mnt/SAN-01/Archive/`

The problem is spaces and getting the correct syntax in the Word Documents folder there are a bunch of Sub folders etc so i need it to be recursive in moving.

Any help would be great.


----------



## ralphbsz (Mar 21, 2019)

First: The conventions for quoting depend on shell.  But I think for the simple things you are doing, that will not matter.

Second: Build it up in pieces.  Start with: "find /mnt/SAN-01/Word\ Documents -type f".  That should give you a list of everything that is a file in that directory.  The only quoting problem you need to solve here is to get the blank into the filename, and what you wrote is correct.  By the way, if you are interested in directories instead of files, replace the above with "type d".

Side remark: You don't need the trailing slash on the directory name.  It doesn't hurt either.  Some versions of find used to create double slashes (which are technically correct but look wierd) if you give them a directory name with a trailing slash.

Next step: Find all the things that have the name you desire.  Personally, I would keep the "type f" or "type d" option too, since you are probably only interested in files or directories, but not both.  Try: "find /mnt/... -name STUFF".  No, you don't need quotes around the name.  And if you do need quotes, in general double quotes "STUFF" work better than single ones (the difference between them is important and subtle, and I don't feel like writing a blob post about it here, read the man pages yourself).  If you do need quoting because "STUFF" contains wildcard characters * or ?, or blanks or punctuation, you are in general better off escaping them with backslashes than quoting.  Once you get this to work, ...

Next step: Add the exec option.  The one you wrote will not work, because exec needs an entry "{}" for the name of the object that was found.  You probably mean "find /mnt/... -type ... -name ... -exec mv {} /new/dir/...", to move the object found to the new place.

Why are you using -R on the mv command?  In FreeBSD, that option doesn't even exist.  And I can't be bothered to look up whether it exists in other OSes.


----------



## phoenix (Mar 21, 2019)

You're missing the filename in your command (note the {} which find replaces with the matching result, in '' to preserve spaces):
`find /mnt/SAN-01/Word\ Documents/ -name 'STUFF' -exec mv '{}' /mnt/SAN-01/Archive/`

Do you want to limit the find to files or directories or both? Add a *-type f* or *-type d* to the command to limit it:
`find /mnt/SAN-01/Word\ Documents/ -type f -name 'STUFF' -exec mv '{}' /mnt/SAN-01/Archive/`


----------



## Ancient (Mar 21, 2019)

Hum...it seems a little very long for execute in 1 only command, don't you think? Nevermind. If I remember well, there's a command more advanced than that: `locate -i` But try to don't forget the advice that you'll see when you type it.
Now you must consider if you really want to execute it at the same time, or, better, execute it following an order, for example: `locate -i`, then once you've found the file, `cd` to the directory in which the file is, and then `mv` the file to the directory that you want. I could post a script, but it will be more complex and may be unnecessary by find only a one file. Or you could know what contains the directory of the file directly without change to it: `ls -l` the directory you want to see.


----------



## Ancient (Mar 21, 2019)

Another thing is that you want to execute that file. Why? It is a script?


----------



## gpw928 (Mar 22, 2019)

Ancient said:


> here's a command more advanced than that: `locate -i`


The locate(1) command relies on an auxiliary database that is pretty much never current , and frequently not even present (it's creation relies on an optional periodic cron job).  Freddie's advice was erudite.


----------



## ralphbsz (Mar 22, 2019)

What you say is true: The locate.updatedb() step is optional, and `locate` is asynchronous.  

But: for large file systems, `find` is impractical to run as an interactive command.  Ever tried it on a file system with a billion files, having directories with millions of files in them?  It will run for impractically long times.  In such an environment, `locate` continues to reasonably efficiently.  Locate is a tool that Unix users and admins have to have in their toolbox; whether to use find or locate is a case-by-case decision, depending on the requirements.


----------



## VladiBG (Mar 22, 2019)

If you have files with same name under different directories you need to create a directory structure first and then move those files into those direcories.

# find all files that contains "STUFF" in they name under /mnt/SAN1/Word Documents/ , extract the dirname from the result, insert prefix "_/mnt/SAN-01/Archive_" and put double quotes around the path to catch the spaces from the directory name and create them under /mnt/SAN-01/Archive/

```
find '/mnt/SAN-1/Word Documents/' -name '*STUFF*' -type f | sed 's#^#"/mnt/SAN-01/Archive#; s#/[^/]*$#"#' | xargs mkdir -p
```

# find all files that contains "STUFF" in they name under /mnt/SAN1/Word Documents/ and execute mv command from the result into the full path with prefix "/mnt/SAN-01/Archive/"

```
find '/mnt/SAN-1/Word Documents/' -name '*STUFF*' -type f -exec mv '{}' '/mnt/SAN-01/Archive/{}' \;
```

Note: this is under csh(1)


----------

