Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

There are some extensionless files in current directory (there are not dot in their names).

I want to rename like so:

filename -> filename.md

I tried doing mv * *.md but that didn't help.

I am interested in a function that takes an argument for the extension and renames accordingly, and the another one for the files to perform operation on.

share|improve this question
add comment

3 Answers

up vote 5 down vote accepted

Patterns are matched by the shell, not by the command, so what you tried had no chance to work: first the shell expands * to all files (not just the extensionless ones: you never said anything about the files not having a . in their name), and *.md to all files whose name in .md; then the shell passes the concatenation of the two lists to the mv command.

In zsh

In zsh, run the following command once (put them in your ~/.zshrc for the future):

autoload -U zmv
# you don't need the following two now, but put them also in your .zshrc
alias zcp='zmv -C'
alias zln='zmv -L'

You can then run zmv to rename files according to a pattern. Both the pattern and the replacement text need to be quoted so that they are passed-as is to the zmv function which will expand them in due course.

zmv '^*.*' '$f.md'

Note the single quotes around both arguments: the pattern and the replacement expression must be passed literally to the zmv function.

^*.* means all files except the ones matching *.*, it's a shortcut for *~*.* (both are zsh extensions to the traditional pattern syntax). If you want to use this pattern outside zmv, you need to run setopt extended_glob first (put that in your .zshrc too).

In bash

Bash has no such convenient tool, so you have to resort to a loop. First, activate ksh globbing extensions; that's something you should put in yout ~/.bashrc.

shopt -s extglob

Now you can use the !(PATTERN) operator to match extensionless files.

for x in !(*.*); do
  mv -- "$x" "$x.md"
done

The double quotes arond $x are necessary in case the file names contain whitespace or globbing characters. The -- after the command name is necessary in case a file name begins with -.

In any shell

If you don't have the !(…) operator, you can loop over all files and test each file name inside the loop.

for x in *; do
  case "$x" in
    *.*) ;;         # skip this file
    *) mv -- "$x" "$x.md";;
  esac
done
share|improve this answer
    
@StephaneChazelas Ah, yes, POSIX does allow an empty command list in case items. I think I got into the habit of using : from an old shell that didn't. I don't remember which one that would be. –  Gilles Mar 23 '13 at 22:33
    
+1 Your answers are always the best :) –  Santosh Kumar Mar 24 '13 at 7:02
add comment

There may be a simpler way, but this one is fairly straightforward and the general form is adaptable to all kinds of purposes:

for name in *; do 
    if [ -f "$name" ]; then 
        mv -- "$name" "$name.md"
    fi
done

It could also be turned into a function.

share|improve this answer
    
Can you make it more readable, I mean can you spread it on multiple lines with proper indentation? –  Santosh Kumar Mar 23 '13 at 17:28
    
These f s are confusing me. Is f (between for and in) and $f same? –  Santosh Kumar Mar 23 '13 at 17:32
1  
This renames all the files in the current directory, not just the extensionless ones. –  Gilles Mar 23 '13 at 20:56
    
@Gilles: True. Rather than expand upon this, since you brought the definitive bomb anyway, I'll just +1 your answer. And all apologies to Santosh for my original use of the one letter variable name, that was thoughtless. –  TAFKA 'goldilocks' Mar 23 '13 at 22:32
add comment

You can do this with rename (the one that comes with perl sometimes renamed prename). If there are other files in the directory, you'll need to exclude those as follows with an extglob:

shopt -s extglob
rename s/$/.md/ -- !(*.*)
share|improve this answer
    
That don't do anything. rename --version says rename from util-linux 2.22.1. –  Santosh Kumar Mar 23 '13 at 17:11
    
Oh, this is rename as shipped with perl. You might need to use prename instead. –  Dennis Kaarsemaker Mar 23 '13 at 17:14
    
There is no prename here on Fedora 18. I have perl v5.16.2 –  Santosh Kumar Mar 23 '13 at 17:17
    
Hmm, minus one for fedora then. Grab it from kaarsemaker.net/static/downloads/prename - it's a pretty short and simple perl script. –  Dennis Kaarsemaker Mar 23 '13 at 17:24
1  
!(patterns) is extended pattern matching operator in BASH (switched on by shopt -s extglob) that matches anything except one of the given patterns. Look for extglob in man bash. –  peterph Mar 23 '13 at 18:07
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.