-1

Test environment:

  • make directories from 0 to 9 and fill them with files from a to z
    $ mkdir {0..9} && touch {0..9}/{a..z}
    
  • Result of find:
    $ find -type f
    ./0/a
    ./0/b
    

    ...

    ./9/y ./9/z

How can I transform the output so that it looks like this:

./0a    
./0b

...

./9y ./9z

benaiu
  • 1

2 Answers2

2

With Perl's standalone rename command:

rename -n 's|/||' */*

If everything looks fine, remove -n and then remove remaining empty directories.

rmdir {0..9}
Cyrus
  • 12,309
0

With POSIX tools,

find . -type f -exec sh -c 'for f; do dirn="${f%/*}"; mv -- "$f" "$dirn${f##*/}"; done' sh {} +

find invokes a shell and executes the for loop for each file.

  • dirn="${f%/*}" gets the parent directory name by excluding all that is after (and including) the last slash in the file name.

  • ${f##*/} gets the filename without the path by excluding all that is before (and including) the last slash in the file name.

Those two shell constructs do the same as dirname and basename, so an equivalent form of the command is

find . -type f -exec sh -c 'for f; do mv -- "$f" "$(dirname "$f")$(basename "$f")"; done' sh {} +

, although this one should be slower as it needs to spawn two extra processes for each file.

If you do not need to descend into more than a single directory, such as your example shows, a simple shell loop does it:

for f in */*; do dirn="${f%/*}"; echo mv -- "$f" "$dirn${f##*/}"; done
Quasímodo
  • 18,865
  • 4
  • 36
  • 73