0

I'm moving png files from source/ to dest/ with this:

mv /source/*.png /dest/

How can I change that command so I only move 10 png files?

Stephen Kitt
  • 411,918
  • 54
  • 1,065
  • 1,164
alexchenco
  • 103
  • 1
  • 5
  • Specify the correct file name pattern, maybe? What about `ls | head -10`? – U. Windl Dec 02 '22 at 07:16
  • @U.Windl see [Why *not* parse `ls` (and what to do instead)?](https://unix.stackexchange.com/questions/128985/why-not-parse-ls-and-what-to-do-instead) – cas Dec 02 '22 at 07:43
  • @cas **I** know how to do that correctly, but I wanted the OP to explain a bit more what he *really* wants to do, or what the real problem is. – U. Windl Dec 02 '22 at 07:47
  • 1
    so why suggest parsing ls? that's just irresponsible, especially if you claim to know better. – cas Dec 02 '22 at 07:56

3 Answers3

4

You can do this in Zsh with a glob qualifier:

mv /source/*.png([1,10]) /dest/

Moves the first 10 ones in alphabetic order. You can pick a different order using the o/O/n qualifiers. For instance:

mv /source/*.png(OL[1,10]) /dest/

Would move the 10 largest ones.

An optimised version that selects the first 10 matches without bothering to sort can be done with the Y qualifier:

mv /source/*.png(Y10) /dest/
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
Stephen Kitt
  • 411,918
  • 54
  • 1,065
  • 1,164
4

POSIXly, that could be done with:

set -- /source/*.png
[ "$#" -le 10 ] || shift "$(( $# - 10 ))"
mv -- "$@" /dest/

Which would move the 10 last ones in alphabetic order.

Note that it excludes hidden ones and if there's no match, it would attempt to move a file called /source/*.png and likely fail.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
-1

ls /source/*.png | head -n10 | xargs -I{} mv {} /dest/

Hobber
  • 369
  • 1
  • 11
  • 1
    This is only safe if you're using a recent version of GNU `ls` with the `--zero` option, combined with `head -z -n 10`, and `xargs -0r ...`. And, since everything else relies on GNU versions, you may as well use GNU `mv`'s `-t` option too. `ls --zero /source/*.png | head -z -n 10 | xargs -0r mv -t dest/`. Even so, it's still better to use `find`: `find /source -maxdepth 1 -name '*.png' -print0 | head -z -n 10 | xargs -0r mv -t dest/`. – cas Dec 02 '22 at 07:43
  • @cas so using `ls --zero` avoids the problem of `never parse ls`? I have no idea about `--zero` and how that works but with your example I understood better. – Edgar Magallon Dec 02 '22 at 16:13
  • 1
    @EdgarMagallon `--zero` is fairly new for GNU ls (first added as --null in July 2021, renamed to --zero a few days later. BTW, according to the changelog, *"--zero also implies -1, -N, --color=none, --show-control-chars"*). I wouldn't say "avoids the problem" - won't help at all for parsing metadata out of `ls -l` (that's what `stat` is for, anyway) but should be OK for just generating a list of NUL-separated files to pipe into other programs or read into an array with `mapfile`. Personally, I'll stick with using `find`, although the convenience of ls's sorting capabilities might be useful. – cas Dec 02 '22 at 16:53
  • @cas thanks for the explanation! That's very clear and useful. I will take a look at the manuals too. As you said it'll be better keep using `find` or `for in /somepath` too – Edgar Magallon Dec 02 '22 at 17:50