0

I have files in subdirectories A, B, C Each directory has files of various names, lets say 1.txt 2.txt 3.txt in each although the names are not relevant as such. I want to run a bash shell script to recurse into each so that the files in each are prefixed with the names of the holding directory so in this example they are renamed A_1.txt, A_2.txt A_3.txt B_1.txt etc.

I currently have


#!/bin/bash                                                                                                                                                                   

for d in ./*/ ;
do cd "$d" ;
for f in "$arg" ;
do  echo mv "$f" "${PWD##*/}""_""${f/_*_/_}";
done
done

but this is failing and I can't see why. Grateful for insights.

This version works for single named files with the argument passed to the shell script but of course has no recursion into the subdirectories although I can use it with the apply command for bulk file processing.


#!/bin/bash                                                                                                                                                                 
for f in "$1" ;
do  mv "$f" "${PWD##*/}""_""${f/_*_/_}";
done

Richard L
  • 33
  • 6
  • What is the directory structure? For example, do you have subdirectories `A`, `B`, and `C` under `/directory`, or do you have `/directory/A/B/C`? I'm just trying to get a better idea of what's there. – Nasir Riley Jun 19 '18 at 23:32
  • it doesn't matter. I just need the name of holding directory of the file in question to be prefixed to that file. Whether the subdirectories are nested or not. – Richard L Jun 20 '18 at 05:44
  • As a further comment - there may be two choices, either I can recurse including the elements of my working single named file shell script (failing first example above building on the working second example) OR have an initiating shell script which has the recursion, which then calls the working single file second example above. In either cases, I am running into problems with the glob expansions. – Richard L Jun 20 '18 at 07:16
  • Solved it (with help from someone's 2014 post in another forum. – Richard L Jun 20 '18 at 23:06

2 Answers2

0
find . -type f -exec sh -c 'for f do x=${f#./}; echo mv "$x" "${x////_}"; done' {} +

Rerun the command without the echo to actually rename/move the files.

@nohillside explained this command here

Ax_
  • 101
  • 2
0
 #!/bin/bash                                                                                                                                                            

 for i in $(ls); do                        # runs through the 'items' in this dir                                                                                       
   if [ -d $i ]; then                      # if this is a dir                                                                                                           
      fname=${i##*/}                 # pick up the dir name which will be used as prefix                                                                                
      echo $fname
      cd $i                                    # move into the dir                                                                                                      
      for z in *; do               # loop over files                                                                                                                    
       echo $z
       mv $z ${fname}_${z}         # put the prefix to the file.                                                                                                       
      done
      cd ..
      fi
   done
Richard L
  • 33
  • 6
  • If that works for what you have then it's cool but it's usually not a good idea to parse `ls`. – Nasir Riley Jun 20 '18 at 23:17
  • Absolutely agree - this was expedient but worked. I'd really appreciate any help with the failing glob expansions in my original question if anyone has solutions. Either as a shell script calling the other script, or having the recursion and rename in one shell script. Either bash or zsh is fine. – Richard L Jun 21 '18 at 10:32
  • The globs not expanding depend on your environment. You may have to escape them with `\`'. – Nasir Riley Jun 21 '18 at 11:36