0

I'd like to rename a group of files to their same filename but without extension. They are scattered in my home directory and I don't know where they are located precisely, but I do know the extension to be removed.

I need to have one and only one command to perform this task.

Here's the partial command:

$ find ~/ -type f -name "*.hhs" -exec mv {} <I DO NOT KNOW> \;

Where <I DO NOT KNOW> is to be replaced by your suggestion. For example, I tried to replace it with the following:

`basename {} .hhs`

It does not work for me.


Example

If files file1.jpg.hhs and file2.jpg.hhs are found, I'd like them to be renamed as follows: file1.jpg and file2.jpg

Faxopita
  • 179

2 Answers2

3

If you have or can install the PERL extension, rename (apt-get install rename on a Debian-based distribution)...

find ~ -type f -name "*.hhs" -exec rename -d ".hhs" {} +

The option, -d or --delete deletes the specified string.

Christopher
  • 15,911
1

You require a tool that can delete the .hhs filename suffix from the filename. find can not do this for you, so you will have to call another utility through -exec:

find "$HOME" -type f -name '*.hhs' -exec sh -c '
    for pathname do
        cp -i "$pathname" "${pathname%.hhs}"
    done' sh {} +

I'm not using basename here as that would also remove the directory path from the found pathnames (which could be inserted again with dirname, but it would yield messy code).

Instead, I call an in-line shell script with as many found pathnames as possible, and let the script loop over these, copying the individual files. The new name is constructed using a standard parameter substitution that deletes the string .hhs from the end of the value of $pathname.

Related:

Kusalananda
  • 333,661
  • @JeffSchaller Noted. – Kusalananda Nov 28 '18 at 14:40
  • +1 Great method, @Kusalananda :-) Please explain how the shellscript works in this case: how is pathname given its value? What is the difference compared to find . -name "*.pdf" -exec bash -c 'echo cp -p "$1" "${1%%.pdf}"' bash {} \; which works for me (I tested locally and for pdf files). – sudodus Nov 28 '18 at 15:14
  • @sudodus I hoped to avoid that explanation by linking to a more expressive general answer regarding the various uses of -exec with find. But in general, find passes the found pathnames to the utility that you call from -exec, replacing {} with the pathname that it has found. With -exec ... {} +, find will replace {} with not one pathname, but with as many as possible. This means that the script that I have is called with a number of pathnames, and the loop in the script loops over these. – Kusalananda Nov 28 '18 at 15:44
  • @sudodus In your example with bash, the bash shell will be invoked once for each file. This is slow if there are many files. – Kusalananda Nov 28 '18 at 15:45
  • Thanks. But one more question. I have learned that a shellscript will use $1 etc as parameters. How come you can use pathname for this purpose? Will the first available variable be used in these cases? – sudodus Nov 28 '18 at 15:52
  • @sudodus I'm looping over the positional parameters with for pathname do. $pathname will be the value of $1, then $2, and $3 etc. – Kusalananda Nov 28 '18 at 15:59