0

I have a problem where I need to rename just certain files after the parent folder and afterwards move these to a central folder. Is there a way to do this? I would like to run this on a Synology NAS.

Root |-Subf1 | |-File.txt | |-File.doc | |-Subf1subf1 | | |-File.xml | | |-File.xls | |-Subf1subf2 | | |-File.pptx | | |-File.docx | |-Subf2 | |-File.txt | |-File.doc | |-Subf2subf1 | | |-File.xml | | |-File.xls 

Result should be:

Root |-Subf1 | |-Subf1.txt | |-Subf1.doc | |-Subf1.xml | |-Subf1.xls | |-Subf1.pptx | |-Subf1.docx | |-Subf2 | |-Subf2.txt | |-Subf2.doc | |-Subf2.xml | |-Subf2.xls 

There is no problem with overwriting files as they all have different extensions.

2
  • Do all the file names start with File? Commented Dec 1, 2020 at 17:36
  • No, they start different Commented Dec 1, 2020 at 20:33

2 Answers 2

0
#! /bin/bash shopt -s globstar #enabled for '**' to match all files &directories recursively #shopt -s dotglob #uncomment to enable to match on hidden files/directories too cd /path/to/directory/Root for pathname in ./**/*; do [[ -f "$pathname" ]] && echo mv -v -- "$pathname" "${pathname%%/*}/${pathname%%/*}.${pathname##*.}"; done ##then remove remained empty directories for pathname in ./**/*; do [[ -d "$pathname" && -z "$(ls -A -- "$pathname")" ]] && rm -r -- "$pathname"; done 
  • [[ -f "$pathname" ]] checks if the $pathname is a file
  • ${pathname%%/*}: Using shell-parameter-expansion, cut the longest suffix from the pathname parameter. cuts everything up-to first slash / character.
  • ${pathname##*.}": same, but this cuts the longest prefix from the pathname parameter; cuts everything up-to last dot . character.
  • [[ -d "$pathname" ]] checks if the $pathname is a directory
  • ... && -z "$(ls -A -- "$pathname")" then checks if basename of the pathname which was a directory, is empty or not.

remove echo when you were happy with the result.

0
0

POSIXly:

cd Root && LC_ALL=C find . \ -name '.?*' -prune -o \ -path './*/*/*' \ -prune \ -name '*.*' \ -type f \ -exec sh -c ' ret=0 for file do ext=${file##*.} sub=${file%/*/*} subname=${sub##*/} echo mv -i "$file" "$sub/$subname.$ext" || ret=$? done exit "$ret"' {} + 

(remove echo if happy)

Empty dirs can be removed afterwards with:

find . -depth -type d -exec rmdir {} + 2> /dev/null 

Or if your find supports the non-standard -empty and -delete:

find . -type d -empty -delete 

(-delete implies -depth).

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.