Cut a field in a string with bash

5,306

Solution 1

You should be using dirname and basename instead of these tricks with rev and cut

declare -l file_lower   # anything assigned to this varname will be lower-cased

find $1 -type f | while read -r file
do
    file_lower=$(basename "$file")
    dir=$(dirname "$file")
    mv "$file" "$dir/$file_lower"
done

find $1 -type d | sort -r | while read -r file
do
    file_lower=$(basename "$file")
    dir=$(dirname "$file")
    mv "$file" "$dir/$file_lower"
done

Solution 2

cut -d/ -f 2-

Cut supports ranges for its offset parameter, e.g. -f 2- , -c -2, -b 1-3

Solution 3

On a GNU system:

find . -depth -name '*[[:upper:]]*' -printf '%h\0%f\0' |
  awk -v RS='\0' '{getline f; printf "%s\0%s\0", $0"/"f, $0"/"tolower(f)}' |
  xargs -r0n2 echo mv

(remove echo when happy).

Or if you can use zsh:

autoload zmv
zmv -n -wQ '**/*(D)' '$1${(L)2}'

(remove -n when happy)

Share:
5,306

Related videos on Youtube

Admin
Author by

Admin

Updated on September 18, 2022

Comments

  • Admin
    Admin almost 2 years

    I need to lower all upper-cases of file and folder names from a path, recursively inside other folders found; I need to do that with a bash script.

    Here my code:

    for file in $(find $1 -type f)
    do
        tmp=$(echo $file | rev | cut -d/ -f1 | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)
        tmp2=$(echo $file | rev | cut ????)
        tmp=$tmp$tmp2
        mv $file $(echo $tmp | rev)
    done
    for file in $(find $1 -type d | sort -r)
    do
        tmp=$(echo $file | rev | cut -d/ -f1 | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)
        tmp2=$(echo $file | rev | cut)
        tmp=$tmp$tmp2
        mv $file $(echo $tmp | rev)
    done
    

    The problem is at line 4, [tmp2=$(echo $file | rev | cut ????)] I don't know how I can select all the fields delimited with / after the first field.

    With line 3 I can isolate the file name and with the tr command modify all upper-cases, but then comes the trouble. Same for folders t the second 'for' construct.

  • Stéphane Chazelas
    Stéphane Chazelas over 10 years
    That assumes file names don't contain newline characters and don't end in space or tab characters. It interprets the first argument as a list of file patterns. sort -r doesn't do what you (and the OP) think it does as there are several characters that sort before / (you want -depth here).