0

I want to use Automator in my Mac with the shell to tidy up my files. I try to write some command like this:

mv -f /Users/myname/Downloads/*.zip /Users/myname/Downloads/zip/
mv -f /Users/myname/Downloads/*.txt /Users/myname/Downloads/txt/

and they worked. But I found that 'mv' will return error if no file matches, so I want to make something like this.

if (txt file) , mv *.txt /txt/
if (zip file) , mv *.txt /zip/

I found that the if statement is using

[ -f "   "]

Then I wrote something like this

[ -f "/Users/myname/Downloads/*.zip" ] && mv -f /Users/myname/Downloads/*.zip /Users/myname/Downloads/zip/ || echo 'Nothing'

But it returns "Nothing" even the files exist.

How can I fix this problem? Or I should not using shell command to do this? Any suggestion?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Pete
  • 170
  • 1
  • 13
  • Possible duplicate of [Test whether a glob has any matches in bash](https://stackoverflow.com/questions/2937407/test-whether-a-glob-has-any-matches-in-bash) – melpomene Feb 18 '18 at 16:52
  • Does it actually matter that `mv` shows an error in this case? You could just ignore it. – that other guy Feb 18 '18 at 17:00

1 Answers1

1

How about using find instead? Something like this:

If you can use mv -t

find /Users/myname/Downloads/ -maxdepth 1 -name "*.zip" -print0 | xargs -0 mv -f -t /Users/myname/Downloads/zip/

If you're unlucky (or use -exec as pointed out in several comments):

find /Users/myname/Downloads/ -maxdepth 1 -name "*.zip" -print0 | xargs -I {} -0 mv -f {} /Users/myname/Downloads/zip/

EDIT added -print0 to make the solution white space safe.

EDIT2 use mv -t instead of {}

Stefan Becker
  • 5,695
  • 9
  • 20
  • 30
  • 2
    You can also use `-exec` instead :) – PesaThe Feb 18 '18 at 17:00
  • I personally always recommend `find` over shell globbing – Stefan Becker Feb 18 '18 at 17:01
  • 2
    Better: `find /Users/mynname/Downloads/ -maxdepth 1 -name '*.zip' -exec mv {} /Users/myname/Downloads/zip/ ';'`. Since `find` now supports `+` instead of `;`, it is often not necessary to use `xargs` with `find` — especially when the names must be processed one at a time. GNU `mv` has an option `-t targetdir` that would allow the use of `+`; it isn't available in the native macOS `mv` command. – Jonathan Leffler Feb 18 '18 at 17:01
  • @PesaThe `-exec` is way inferior to `xargs`, because `xargs` reduces the number of sub-processes created. This might not matter with a few files, but does really matter when 100s or 1000s of files are involved. – Stefan Becker Feb 18 '18 at 17:03
  • @StefanBecker: The `xargs` command shown in the answer must create one process per file name — as must the `find` shown in my comment. I extended my other comment to cover the point more thoroughly while you were adding your comment. (The first version was brief and accurate, but not as explanatory.) – Jonathan Leffler Feb 18 '18 at 17:04
  • Plus `xargs` knows how to detect the maximum command line length, so the above solution will work without changes on MinGW on Windows (128K characters?) vs. Linux (2MB characters usually) – Stefan Becker Feb 18 '18 at 17:05
  • Ah yes, that's why usually avoid `{}` but always forget :-) – Stefan Becker Feb 18 '18 at 17:07