I have a file list like this (long list, not all):

enter image description here And I want to filter the files with keywords "QM" and ".h5", so I type ls|grep "QM"|grep "h5" and it shows these (what I need) enter image description here

So basically I want to move these files to another directory, but I don't know how to move them with one line of script.

Also, is there a way to randomly choose 5 of these files and copy them to another directory?

  • 2
    Shell globs (ex. *QM*.h5) are going to be your friends here Jan 1, 2020 at 4:12
  • Thanks, it solved.
    – Negrito
    Jan 1, 2020 at 5:33

3 Answers 3


Shell globs are going to be your friends here.

For example, instead of using grep, you can list all files whose names contain QM and end with .h5 using

ls *QM*.h5

You can use globs in mv and cp operations provided that the number of matching files is not too large

cp *QM*.h5 path/to/new_dir/

If the number of files is too large, you may get an argument list too long error; you can work around that using the shell's printf builtin with xargs to break the copy into manageable chunks:

printf '%s\0' *QM*.h5 | xargs -0 cp -t path/to/new_dir/

With bash, there's no intrinsic way to limit the number of files selected (or to select a random subset) but you could do so by adding a call to shuf:

printf '%s\0' *QM*.h5 | shuf -zn5 | xargs -0 cp -t path/to/new_dir/

Note that I used the null byte \0 instead of the newline character to delimit the list of filenames - that's not necessary in your case, but makes the command usable in the more general case where filenames themselves may contain newlines.

If you don't mind switching to the z shell zsh, then you can select a random subset without resorting to external utilities, using the shell's more expressive glob qualifiers:

cp -t path/to/new_dir/ *QM*.h5(Nnoe['REPLY=$RANDOM'][1,5])        # zsh only

Related question on our Unix & Linux sister site:


"Many files"? "Files with funny characters in their name"?

This calls for find and xargs!

Read man find;man xargs and do something like:

find . -maxdepth 1 -name '*QM*.h5' -print0 |\
  xargs -0 --no-run-if-empty mv --target-directory=AnotherDirectory

Note: "AnotherDirectory" must already exist.

Note: See what the results will be by initaiily replacing "mv" with "echo mv".

  • it says ´mv: failed to access '~New_dir': No such file or directory´ . I created this New_dir
    – Negrito
    Jan 1, 2020 at 5:30
  • ~NewDir refers to (nonexistent) user "NewDir""s HOME directory. Use ~/NewDir.
    – waltinator
    Jan 1, 2020 at 23:47
  • Sorry, I mean the "New_dir", still it doesn't work. I guarantee that I mkdir the directory and it is properly referred.
    – Negrito
    Jan 2, 2020 at 2:00

Just cp *QM*.h5 target_dirand done.

  • This doesn't answer the whole question, otherwise it is a duplicate of this existing answer: askubuntu.com/a/1199883
    – karel
    Jan 1, 2020 at 8:09
  • And will NOT work if many (thousands) of files match. Been there, made that mistake.
    – waltinator
    Jan 1, 2020 at 23:52

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.