Ben McCormick
Ben McCormick

Reputation: 25728

Changing file extensions for all files in a directory on OS X

I have a directory full of files with one extension (.txt in this case) that I want to automatically convert to another extension (.md).

Is there an easy terminal one-liner I can use to convert all of the files in this directory to a different file extension?

Or do I need to write a script with a regular expression?

Upvotes: 91

Views: 94931

Answers (12)

seidnerj
seidnerj

Reputation: 441

Not sure if this was a mistake in the original accepted answer, but the original answer ADDS the .md file extension, it does not REPLACE the file extension. Also, the original answer would not work for filename with spaces in them. This worked for me:

for old in *.txt; do mv "$old" "`echo "${old%.*}"`.md"; done

Upvotes: 0

xel
xel

Reputation: 11

If you're using the zsh shell

autoload -U zmv
zmv '(**/)(*).txt' '$1$2.md'

Upvotes: 0

Akhil Kokani
Akhil Kokani

Reputation: 347

You do not need a terminal for this one; here is a sample demonstration in MacOS Big Sur.

  • Select all the files, right-click and select "rename..." enter image description here

  • Add the existing file extension in "Find" and the extension you want to replace with "Replace with". enter image description here

And done!

Upvotes: 11

securitygeek
securitygeek

Reputation: 1

list=ls for file in $list do newf=echo $file|cut -f1 -d'.' echo "The newf is $newf" mv $file $newf.jpg done

Upvotes: 0

Ken Richardson
Ken Richardson

Reputation: 11

I had a similar problem where files were named .gifx.gif at the end and this worked in OS X to remove the last .gif:

for old in *.gifx.gif; do
    mv $(echo "$old") $(echo "$old" | sed 's/x.gif//');
done

Upvotes: 1

Renaud
Renaud

Reputation: 16501

Alternatively, you could install the ren (rename) utility

brew install ren

ren '*.txt' '#1.md'

If you want to rename files with prefix or suffix in file names

ren 'prefix_*.txt' 'prefix_#1.md'

Upvotes: 86

Saurabh Bhoomkar
Saurabh Bhoomkar

Reputation: 605

No need to write a script for it just hit this command

find ./ -name "*.txt" | xargs -I '{}' basename '{}' | sed 's/\.txt//' | xargs -I '{}' mv '{}.txt'  '{}.md'

Upvotes: 4

LBC
LBC

Reputation: 326

The preferred Unix way to do this (yes, OS X is based on Unix) is:

ls | sed 's/^\(.*\)\.txt$/mv "\1.txt" "\1.md"/' | sh

Why looping with for if ls by design loops through the whole list of filenames? You've got pipes, use them. You can create/modify not only output using commands, but also commands (right, that is commands created by a command, which is what Brian Kernighan, one of the inventors of Unix, liked most on Unix), so let's take a look what the ls and the sed produces by removing the pipe to sh:

$ ls | sed 's/^\(.*\)\.txt$/mv "\1.txt" "\1.md"/'
mv "firstfile.txt" "firstfile.md"
mv "second file.txt" "second file.md"
$

As you can see, it is not only an one-liner, but a complete script, which furthermore works by creating another script as output. So let's just feed the script produced by the one-liner script to sh, which is the script interpreter of OS X. Of course it works even for filenames with spaces in it.

BTW: Every time you type something in Terminal you create a script, even if it is only a single command with one word like ls or date etc. Everything running in a Unix shell is always a script/program, which is just some ASCII-based stream (in this case an instruction stream opposed to a data stream).

To see the actual commands being executed by sh, just add an -x option after sh, which turns on debugging output in the shell, so you will see every mv command being executed with the actual arguments passed by the sed editor script (yeah, another script inside the script :-) ).

However, if you like complexity, you can even use awk and if you like to install other programs to just do basic work, there is ren. I know even people who would prefer to write a 50-lines or so perl script for this simple every-day task.

Maybe it's easier in finder to rename files, but if connected remotely to a Mac (e.g. via ssh), using finder is not possible at all. That's why cmd line still is very useful.

Upvotes: 11

James Tomasino
James Tomasino

Reputation: 3581

Based on the selected and most accurate answer above, here's a bash function for reusability:

function change_all_extensions() {
    for old in *."$1"; do mv $old `basename $old ."$1"`."$2"; done
}

Usage:

$ change_all_extensions txt md

(I couldn't figure out how to get clean code formatting in a comment on that answer.)

Upvotes: 4

Vicky
Vicky

Reputation: 549

Terminal is not necessary for this... Just highlight all of the files you want to rename. Right click and select "Rename ## items" and just type ".txt" into to the "Find:" box and ".md" into the "Replace with:" box.

Upvotes: 54

Manish Ranjan
Manish Ranjan

Reputation: 11599

    cd $YOUR_DIR
    ls *.txt > abc
    mkdir target // say i want to move it to another directory target in this case
    while read line
    do 
    file=$(echo $line |awk -F. '{ print $1 }')
    cp $line target/$file.md  // depends if u want  to move(mv) or copy(cp)
    done < abc

Upvotes: 0

Pascal Belloncle
Pascal Belloncle

Reputation: 11389

You could use something like this:

for old in *.txt; do mv $old `basename $old .txt`.md; done

Make a copy first!

Upvotes: 154

Related Questions