Ubuntu – Rename a file to parent directory’s name in terminal

bashcommand line

I have to deal with a large number of files nested inside of directories (one file per directory), resembling something like this:

fred/result.txt
john/result.txt
mary/result.txt
...

I am currently using the following command to process each of those files:

find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c \"cd '{}' && processResult result.txt\" \;

I am looking for something I can add into the end of this command that will change the filenames to fred.txt, etc. and then later move the file into the parent directory to eliminate the extra layer of directories.

What would be the best way to do this?

Best Answer

We can use the classical approach : find with while read combo:

Demo:

$ ls *
fred:
results.txt

jane:
results.txt

john:
results.txt

$> find . -type f -name "results.txt" -printf "/%P\n" | while read FILE ; do DIR=$(dirname "$FILE" );\                            
>  mv ."$FILE" ."$DIR""$DIR".txt;done                                                                                             
$> ls
fred/  jane/  john/
$> ls *
fred:
fred.txt

jane:
jane.txt

john:
john.txt

Use echo before using mv to test the line with your files.

Minor improvement

We can embed the call to bash into exec , with parameter expansion (specifically prefix removal). Basically it's embedding a script into exec call.

$> find "$PWD" -type f -name "results.txt" -exec bash -c ' DIR=$( dirname "{}"  ); echo "{}" "$DIR"/"${DIR##*/}".txt  ' \;                
/home/xieerqi/TESTDIR/fred/results.txt /home/xieerqi/TESTDIR/fred/fred.txt
/home/xieerqi/TESTDIR/jane/results.txt /home/xieerqi/TESTDIR/jane/jane.txt
/home/xieerqi/TESTDIR/john/results.txt /home/xieerqi/TESTDIR/john/john.txt

To make the command general, (working for any file, not just results.txt) just remove -name "results.txt" part. Also see this post for alternative Python solution to this.