I have a directory containing several sub-directories, containing files.

I would like to sort the files in each of these directories by name alphabetically and copy the first file from each directory to a given new directory.

  • I would like to ignore hidden files.
  • If there is a file with the same name in the destination directory, both files should be kept.



I would like to run a command that would populate my new directory like so:


How can this be accomplished?

  • How do you define 'first' then?
    – ilkkachu
    Dec 24, 2017 at 13:16
  • i know there are some examples on how to move first x amount of files. i am just figuring linux internal mechanics could sort that out?. thought about a modified version from this #find . -maxdepth 1 -type f |head -1000|xargs cp -t "$destdir"
    – dekatch
    Dec 24, 2017 at 13:21
  • 1
    Please edit your question and explain what you mean by "first". First by date? First by alphabetical order? Just any random file? What about hidden files? Do they count? Is the new destination a directory? What if you have files with the same name? Should they be overwritten?
    – terdon
    Dec 24, 2017 at 13:25
  • ok, done terdon. whew.. dunno if i still feel comfortable with that requests ! i think i ask for to much xx
    – dekatch
    Dec 24, 2017 at 13:37

3 Answers 3


I guess the straightforward way is to use ls to list the files, which it does in alphabetical order (and omitting hidden files) by default, take the first one from each directory with head, and then have a bit of shell code to figure out what filename they should be copied to. As in this bash script:

for d in ./*/; do
    src="$(ls "$d" | head -n 1)"
    dstbase="newdir/$(basename "$src")"
    if [[ ! -f "$dstbase" ]]; then
        cp "$src" "$dstbase"
        while [[ -f "$dstbase.$suffix" ]]; do
            let suffix++
        cp "$src" "$dstbase.$suffix"

Obviously you will have to adjust the file paths as needed for your actual situation. This is also fairly fragile in the sense that it may have problems if there are any directories under dir1, dir2, etc. which you would want to exclude from being copied. It also has a potential race condition in the loop that looks for an unused filename; that probably won't be a problem, but don't do anything like running multiple copies of this in parallel.


This can be achieved with the following one line:

ls -ltr /parent_directory_path/ |
awk '$1~"^drw" {print $9}' |
while read line; do
  ls -l $line |
  awk '$1 ~ "^-r" {print $9}' |
  head -1 |
  awk -v line="$line" '{print "cp -rvfp"  "  " line"/"$1 " " "/newdir/" }';
done |

With zsh and GNU cp:

cd parentdir &&
  for dir (*(/)) (cp --backup=numbered -- $dir/*(.[1]) newdir/)

the --backup=numbered implements a backup scheme where files are named file.~1~, file.~2~... So the first copy will make will be file.~max~ and the last one file (process the list backward (*(/On) instead of *(/)) if you want the order reversed).

POSIXly, you could do:

cp_numbered() (
  while [ -e "$2$suffix" ] || [ -L "$2$suffix" ]; do
    suffix=.$((n += 1))
  exec cp -- "$1" "$2$suffix"
cd parentdir &&
  for dir in */; do
    for file in "$dir"/*; do
      if [ -f "$file" ]; then
        cp_numbered "$file" "newdir/${file#*/}"
        continue 2

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .