Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

It was a mess of music files and directory.

It is needed to perform the below operation over multiple directories at once:

  1. If the directory contains ".jpg" files, then create a new directory "Covers" and move those files into it.
  2. If the directory does not contain any ".jpg" files, don't create "Covers" directory
  3. If the directory already contains "Covers" directory, don’t create "Covers" directory
share|improve this question
up vote 3 down vote accepted

In bash:

shopt -s nullglob
for dir; do
    [[ -d $dir ]] || continue
    jpgs=( "${dir}"/*.jpg )
    if (( "${#jpgs[@]}" )); then
        [[ -d ${dir}/Covers ]] || mkdir "${dir}/Covers"
        # Avoiding race condition by not reusing the jpgs array
        for jpg in "${dir}"/*.jpg; do
            mv "$jpg" "${dir}/Covers"
share|improve this answer
pretty simple and neat, @Chris-down :-) – Nikhil Mulley Mar 3 '12 at 10:43
@Chris-down, darn that is awesome :) – user14517 Mar 3 '12 at 14:16
@Chirs Down, Awesome sir :) – user1228191 Mar 3 '12 at 15:09

I am still a rookie but here is mine:

#echo $current_directory
(find -maxdepth 1 -type d -name '*' ! -name '.*' -printf '%f\n')>filelist
number=$(find -maxdepth 1 -type d -name '*' ! -name '.*' -printf '%f\n' | wc -l)
for iteration in `seq $number`
    fname=$(head -1 filelist)
    sed 1d < filelist > filelist2
    mv filelist2 filelist
    cd "$fname"
    if [ -z $(ls | grep -i jpg) ]
    then echo "Doing nothing as there are no JPG files....."
        total=$(ls -l|grep -i jpg | wc -l)
        mkdir -p Covers
        mv *.jpg Covers
        echo "Moved $total JPG Files....."
    cd "$current_directory"

Simply go into the main music directory and execute this script.

No need to pass any arguments

EDIT: It was sloppy before. It is sloppier now. But I think it will work.

share|improve this answer
Thanks its very nice, Same question for you too : How to get handle those directory names which contains spaces in its name – user1228191 Mar 3 '12 at 9:34
Oh. Nice catch. I'll work on it. – user14517 Mar 3 '12 at 9:53
Do not parse ls, it is dangerous and will break easily. Use a glob. See mywiki.wooledge.org/ParsingLs – Chris Down Mar 3 '12 at 10:18
Also, you need to quote $current_directory, or it will break if the path has spaces in. – Chris Down Mar 3 '12 at 10:34
Yes, it will. Don't parse ls! – Chris Down Mar 3 '12 at 11:02


#work in current dir if work path was not provided  
[ $# -eq 0 ] && search_path="." || search_path="$1"  

# files to be moved, more extensions can be added  

move_jpg() {  
    # create "Covers" if it doesn't exist  
    [ -d "$1/Covers" ] && echo -n " ... " || { echo -n " ...create Covers ";   mkdir "$1/Covers" }  

    mv "$1/$wildcard" "$1/Covers/$wildcard"  
    echo "... files moved"  

for d in "$search_path/*/"; do  

    echo -n "testing <$d>   "  

    [ -e "$d/$wildcard" ] && ${move_jpg "$d"} || echo "...Not found <$wildcard>"  


share|improve this answer
Using command substitution with find will break very easily. Do not do it. – Chris Down Mar 3 '12 at 10:19
Instead of calling find, which will break on all kinds of file names, write for d in "$search_path"/*/; the final / restricts the matching to directories. I wonder where IFS=$(echo -en "\n\b") comes from (by the way, you can write this in a simpler way: IFS=$'\n\b'): what's the point in making backspace a field separator? – Gilles Mar 3 '12 at 23:51
didn't know about trick with last slash, will use it, thanks. of cause, IFS=$(echo ...) can be easily replaced to just assignement. corrected. – vasily-vm Mar 6 '12 at 16:53
"Using command substitution with find will break very easily" don't understand this :( how find can be broken in such situation? – vasily-vm Mar 6 '12 at 16:57

Your Answer


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.