1

When I run the following:

mv -v foo /mnt/bar

The directory foo and all it's sub contents is moved into the directory /mnt/bar. The order that files are moved appears to be directory order (ls -U).

Is there a good way to perform this same operation but ensure that the sub files/directories of foo are moved in alphabetical order?

I realise I can use find -exec mv to iterate the sub contents in alphabetical order but this requires some annoying gymnastics to maintain the same subdirectory structure in the target. I was hoping for a flag on GNU mv but the man page shows nothing useful.

  • 1
    What's the purpose of moving them in a specific order? And if it needs to be alphabetial, does mv foo/* /mnt/bar/ solve your problem? – nohillside Aug 5 '18 at 20:55
  • I would second this question - what is the reason behind wanting to move the files in alphabetical order? Ext4 does not store the files in alphabetical order on disk, regardless of the order that you copy them in (it uses hash order for any directory with more than about 150 filenames, and the hash order is different for each filesystem). Newer versions of fileutils will process the files in inode order to minimize the disk seeks, so it is best to leave it to handle the files in the order it wants unless there is a good reason not to. – LustreOne Aug 7 '18 at 7:18
  • For example: I am moving files that have somewhat predictable naming. It's easy to see at a glance the progress of the mv -v command by looking at the name of the file currently being moved IF the files are moved in alphabetical order. If the files are moved in a random (name hash) order then it's hard to tell how far through the mv operation we are. – joelittlejohn Aug 7 '18 at 16:09
2
$ \ls foo | xargs -I% mv -v foo/% bar
'foo/one' -> 'bar/one'
'foo/sie' -> 'bar/sie'
'foo/two' -> 'bar/two'
'foo/uve' -> 'bar/uve'
'foo/wox' -> 'bar/wox'
'foo/zanzibar' -> 'bar/zanzibar' 
  1. Use ls to list items alphabetically. To make sure you're running pure ls (with no additional characters added by an alias hidden away in your .bashrc or .bash_aliases), run the command as \ls.
  2. Send output of ls to xargs
  3. Give each item a variable name with the -I variable (this just gives you something to "see" in your mv command)
  4. Move your item (called %) from its location in foo to the new destination.
1

With zsh and a pax implementation supporting -0:

printf '%s\0' foo foo/**/*(D) | pax -0rwdv /mnt/bar/ && rm -rf foo

Those recursive globs are sorted lexically (using the locale's collation order) at each level. a before a/a before a/b before b...

Note that it's not the same as find foo -print0 | sort -z which sorts the paths as a whole and would for instance sort:

a
a/b
a/b.c
a/b/c

In that order in the C locale instead of:

a
a/b
a/b/c
a/b.c

in zsh globs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.