LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   mv: target `filename' is not a directory (https://www.linuxquestions.org/questions/programming-9/mv-target-%60filename-is-not-a-directory-745600/)

dai_bach 08-06-2009 11:31 AM

mv: target `filename' is not a directory
 
I'm trying to write a short script that changes the file names in the folders containing music (mp3) files. The current format is often along the lines of:
"Artist Name - Album Name - tracknum - Trackname.mp3"
and I'd like to shorten this to just:
"tracknum Trackname.mp3"

So, I've tried the following approach
Code:

for i in *.mp3; do
  j=`echo $i | cut -d "-" -f3`; #results in "tracknum"
  k=`echo $i | cut -d "-" -f4`; #results in "Trackname.mp3"
  mv $i $j$k;
done

but I get the error:
Code:

mv: target `Trackname.mp3' is not a directory
I'm not expecting it to be a directory! As far as I'm aware, $j$k should give me "tracknum Trackname.mp3". Indeed, this is the result of
Code:

echo $j$k
Could someone please tell me where I'm going wrong or how to solve my problem?

Cheers

David the H. 08-06-2009 11:42 AM

I'll bet the problem is spaces in your filenames. They can really mess up scripting. Most *nix users learn to avoid them in filenames whenever possible.

Add this to the start of your script. It changes the internal field separator to a newline only, and your script will treat spaces as just another character from then on.
Code:

#!/bin/bash

IFS='
'

<your script>

Also, take some time to learn about how quotes work in shells and scripts. Surrounding your variables in double-quotes will generally work too. I usually prefer changing the IFS though, as it's more foolproof.

David the H. 08-07-2009 01:07 PM

So I take it it worked then. :)

dai_bach 08-08-2009 02:00 AM

Aye, worked a treat. Cheers!

fqaiser 11-19-2012 11:46 PM

Install: target p is not a directory
 
I have an error same as per above 'Title'. In fact i am trying to install aircrack-2.41 on Backtrack 5 which is installed on Virtual Box. It will come to terminal screen when;

I run a command 'root@bt:~/aircrack-2.41# make install'.

In result of this i found following response;

a) install -d /usr/local/bin
b) install -m 755 aircrack airdecap arpforge aireplay airodump airmon.sh mergeivs p
c) cap2inv /usr/local/bin

When i try to apply [install -m 755 aircrack airdecap arpforge aireplay airodump airmon.sh mergeivs p ] it appears like this;

[root@bt:~/aircrack-2.41#install -m 755 aircrack airdecap arpforge aireplay airodump airmon.sh mergeivs p]

install: target p is not a directory

Can somebody please help me to solve this problem?? why p directory is not found?? can i create a p directory myself to complete install??
help me....!!!!!!!!!!!!!!

fqaiser 12-19-2012 02:24 AM

Quote:

Originally Posted by fqaiser (Post 4833011)
I have an error same as per above 'Title'. In fact i am trying to install aircrack-2.41 on Backtrack 5 which is installed on Virtual Box. It will come to terminal screen when;

I run a command 'root@bt:~/aircrack-2.41# make install'.

In result of this i found following response;

a) install -d /usr/local/bin
b) install -m 755 aircrack airdecap arpforge aireplay airodump airmon.sh mergeivs p
c) cap2inv /usr/local/bin

When i try to apply [install -m 755 aircrack airdecap arpforge aireplay airodump airmon.sh mergeivs p ] it appears like this;

[root@bt:~/aircrack-2.41#install -m 755 aircrack airdecap arpforge aireplay airodump airmon.sh mergeivs p]

install: target p is not a directory

Can somebody please help me to solve this problem?? why p directory is not found?? can i create a p directory myself to complete install??
help me....!!!!!!!!!!!!!!

My problem has been solved as it is already installed & i use /usr/local/bin to use aircrack. Many Thanks.

David the H. 12-19-2012 02:14 PM

First of all, please don't re-open old threads unless you have something substantial to add to that discussion, such as a correction or updated information. If you have a new question of your own, start a new thread and refer back to the old one if necessary. Thanks.

Besides, I don't think your question has anything directly to do with the original subject here. His problem was with improperly quoted variables leading to word-splitting in the arguments, while yours seems to have something to do with either the syntax of your install command or the conditions of the directory you passed to it. But I'm not familiar with that comman, so I can't say.


But you have given me an opportunity to update one of my old posts. :D After several more years of experience, I would no longer give the advice that I did then.

First, I now understand that changing IFS should be generally avoided, due to possible obscurity in what the code is doing, and that proper quoting is usually the best solution.

Second, when you do need to change IFS to newline or other non-printing characters, you can use ansi-c style quoting:

Code:

IFS=$'\n'
Third, I would recommend the use of built-in string manipulation techniques, rather than cut.

Code:

for fname in *.mp3; do

        newname="${fname#* - * - }"        #results in "tracknum - trackname.mp3"
        newname="${newname// - / }        #changes the " - " to " "
        mv "$fname" "$newname"

done


Xeratul 12-19-2012 11:49 PM

Quote:

Originally Posted by dai_bach (Post 3633792)
I'm trying to write a short script that changes the file names in the folders containing music (mp3) files. The current format is often along the lines of:
"Artist Name - Album Name - tracknum - Trackname.mp3"
and I'd like to shorten this to just:
"tracknum Trackname.mp3"

So, I've tried the following approach
Code:

for i in *.mp3; do
  j=`echo $i | cut -d "-" -f3`; #results in "tracknum"
  k=`echo $i | cut -d "-" -f4`; #results in "Trackname.mp3"
  mv $i $j$k;
done

but I get the error:
Code:

mv: target `Trackname.mp3' is not a directory
I'm not expecting it to be a directory! As far as I'm aware, $j$k should give me "tracknum Trackname.mp3". Indeed, this is the result of
Code:

echo $j$k
Could someone please tell me where I'm going wrong or how to solve my problem?

Cheers










you need :

Code:

find -iname "*.mp3" | while read -r i ; do  echo "$i" ; done
or use this:


Code:


#!/bin/sh 


echo "#############################################"
echo "SHELL : $SHELL"
echo "BASH : $BASH"
echo "TERM : $TERM"
DATENOW=`date +%Y%m%d-%H%M%S`
# last argument
LASTARG=`echo "$@" | awk ' { print $NF  }  '`
# penultimate argument
num_args=$#
num_args_max=$num_args
let num_args=$num_args-1
PENUARG=` echo "$@" | awk -v vk=$num_args ' { print $vk  }  ' `
TRG="$LASTARG"
[ ! -d ~/.config/bashmv ] && mkdir -p ~/.config/bashmv
echo "$DATENOW - $@" >> ~/.config/bashmv/bash-ops-inputs.log
echo "#############################################"







ProcedureStartCopyOneFile() {
  echo "*** COPY ***"
  echo "File not exists : $FILETRG" >> ~/.config/bashmv/bashmv.log
  echo -en "\r Copying ($i) (...)"
  echo "$i" | cpio -pvdmu "$TRG"
  echo -en "\r Copied ($i)."
  TRSS=` du -hs "$FILETRG" --apparent-size | cut -f 1 `
  SRSS=` du -hs "$i" --apparent-size | cut -f 1 `
  if  [ ! -d  "$i" ] &&  [ "$SRSS" != "$TRSS" ] ; then
    echo "Different size: $FILETRG"
    echo "** WARNING **"
    echo "Different size: $FILETRG" >> ~/.config/bashmv/bashmv.log
    echo "** WARNING **" >> ~/.config/bashmv/bashmv.log
    exit
  else
    echo -en "\r Copied ($i) [OK]"
  fi
  echo "*** COPY OK ***"
  echo ".*.*"
}







ProcedureCopying() {

 echo "> Parameters: Source: $SRC  => Target: $TRG"


if [ -f "$SRC" ] || [  -d "$SRC" ] ; then
  echo "Source: $SRC"
else
  echo "Directory or file source $SRC not found."
  exit
fi

if [ "$TRG" = "" ] ; then
  exit
fi





if [ "$BASH" != "/bin/bash" ] ; then
  echo "Warning: You should use BASH : /bin/bash !"
  exit
else
  echo "Intpreter BASH: $BASH [OK] "
fi





echo "** START ** "



[ ! -d  "$TRG" ] && mkdir -p "$TRG"
if [ "$LASTARG" = "--debug" ] ; then
  find "$SRC" -print
  exit
fi

find "$SRC" -print | grep -v "^$\|^#" | while read -r i ; do
# echo "Processing $i"

FILETRG="${TRG}/${i}"
DATENOW=`date +%Y%m%d-%H%M%S`
echo "> Start: .*.* ($i)"
if [ !  -f "$FILETRG" ] && [ ! -d  "$i"  ] ; then
  echo ".*.*"
  echo "*** COPY ***"
  echo "File not exists : $FILETRG" >> ~/.config/bashmv/bashmv.log
  echo "$i" | cpio -pvdmu "$TRG"
  TRSS=` du -hs "$FILETRG" --apparent-size | cut -f 1 `
  SRSS=` du -hs "$i" --apparent-size | cut -f 1 `
  if  [ ! -d  "$i" ] &&  [ "$SRSS" != "$TRSS" ] ; then
    echo "Different size: $FILETRG"
    echo "** WARNING **"
    echo "Different size: $FILETRG" >> ~/.config/bashmv/bashmv.log
    echo "** WARNING **" >> ~/.config/bashmv/bashmv.log
    exit
  else
    echo "Copied ($i) [OK]"
      echo "    - Del file: $i since ok"
      rm "$i"
  fi
  echo "*** COPY OK ***"
  echo ".*.*"


elif [  -d "$i" ] ; then
  mkdir -p "$FILETRG"
  echo "Creating $FILETRG"

elif [ ! -d "$i" ] ; then
  TRSS=` du -hs "$FILETRG" --apparent-size | cut -f 1 `
  SRSS=` du -hs "$i" --apparent-size | cut -f 1 `
  # echo "Source: $SRSS vs $TRSS"


  if  [ -d  "$i" ] ; then
    echo "Directory."
  fi

  if  [ ! -d  "$i" ] ; then
    if [ -f "$FILETRG" ] && [ "$SRSS" = "$TRSS" ] ; then
      echo "file $FILETRG exists. [Same size]"
      echo "    - Del file: $i since ok"
      rm "$i"
    fi

    if  [ "$SRSS111kkk" = "$TRSS" ] ; then
      echo "Different size: $FILETRG"
      echo "** WARNING **"
      echo "Different size: $FILETRG" >> ~/.config/bashmv/bashmv.log
      echo "** WARNING **" >> ~/.config/bashmv/bashmv.log
      FILETRGERROR="${TRG}/Error/${i}"
      [ ! -d  "$TRG/Error" ] && mkdir -p "$TRG/Error"
      echo "$TRSS" | cpio -pvdmu  "$TRG/Error/${DATENOW}-${i}"
      echo "Error. Stopped"
      exit
    fi
  fi
fi



done

echo "Completed. Finished!"


if [ "$LASTARG" = "--rm" ] ; then
  echo "Delete the directory: $SRC [y/n] ? "
  read inpud
  [ "$inpud" = "n" ] && exit
  rm -rf "$SRC"
fi


exit

echo "Calculating... "
echo "Cmd:  du -hs $SRC"
SIZE1=` du -hs "$SRC" | cut -f 1 `
echo "Source: $SIZE1"

echo "Cmd:  du -hs $TRG"
SIZE2=` du -hs "$TRG" | cut -f 1 `
echo "Target: $SIZE2"

if [ "$SIZE1" = "$SIZE2" ] && [ "$LASTARG" = "--rm" ] ; then
  echo "Delete the directory: $SRC [y/n] ? "
  read inpud
  [ "$inpud" = "n" ] && exit
  rm -rf "$SRC"
fi

}











counter=1
echo "Args: $num_args"
seq 1 1 "$(( $num_args +1))" | while read -r each ; do
  if [ $counter -lt $num_args_max ] ; then
    SRC=` echo "$@" | awk -v vk=$counter ' { print $vk  }  ' `
    echo "> $each : $SRC"
    echo "Copying : $SRC to $TRG"
    ProcedureCopying
    echo 
  fi
  counter=$(( $counter +1))
done
exit



# this does mv or backup


David the H. 12-20-2012 06:20 AM

@Xeratul, This is what I was talking about. The thread is over three years old, and I'm sure the OP has long ago moved on to new things. The only reason to add anything new is to help others coming across it later.


As for your suggestions, find is only necessary if you need to search recursively or otherwise match files by criteria that simple globbing can't handle, and even then you shouldn't just pipe the results directly into a loop like that.

Unix file paths can contain any character (except one), so there's always a chance that one can contain an embedded newline. The exception is the null, which is why it's recommended for use as the delimiting character in cases like this.

How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?
http://mywiki.wooledge.org/BashFAQ/001

How can I find and deal with file names containing newlines, spaces or both?
http://mywiki.wooledge.org/BashFAQ/020

There are other issues involved too. If your changes include modifying the pathname, for example, you need to be sure to use the -depth option to process things in a safe order. And anything done in a pipe chain may suffer from subshell-related variable scoping.


How can I rename all my *.foo files to *.bar, or convert spaces to underscores, or convert upper-case file names to lower case?
http://mywiki.wooledge.org/BashFAQ/030

I set variables in a loop that's in a pipeline. Why do they disappear after the loop terminates? Or, why can't I pipe data to read?
http://mywiki.wooledge.org/BashFAQ/024

So to safely use find, something like this would be better:
Code:

while IFS='' read -r -d '' fname ; do
        echo "$fname"
done < <( find . -depth -type f -name '*.mp3' -print0 )

Finally, and I should've mentioned this yesterday, there are a multitude of batch renaming options available, and an unbelievable number of previous discussions on this same topic. If you want to know more, just do a bit of searching in the archives or the web.

Xeratul 12-20-2012 07:58 AM

Quote:

Originally Posted by David the H. (Post 4853604)
@Xeratul, This is what I was talking about. The thread is over three years old, and I'm sure the OP has long ago moved on to new things. The only reason to add anything new is to help others coming across it later.


As for your suggestions, find is only necessary if you need to search recursively or otherwise match files by criteria that simple globbing can't handle, and even then you shouldn't just pipe the results directly into a loop like that.

Unix file paths can contain any character (except one), so there's always a chance that one can contain an embedded newline. The exception is the null, which is why it's recommended for use as the delimiting character in cases like this.

How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?
http://mywiki.wooledge.org/BashFAQ/001

How can I find and deal with file names containing newlines, spaces or both?
http://mywiki.wooledge.org/BashFAQ/020

There are other issues involved too. If your changes include modifying the pathname, for example, you need to be sure to use the -depth option to process things in a safe order. And anything done in a pipe chain may suffer from subshell-related variable scoping.


How can I rename all my *.foo files to *.bar, or convert spaces to underscores, or convert upper-case file names to lower case?
http://mywiki.wooledge.org/BashFAQ/030

I set variables in a loop that's in a pipeline. Why do they disappear after the loop terminates? Or, why can't I pipe data to read?
http://mywiki.wooledge.org/BashFAQ/024

So to safely use find, something like this would be better:
Code:

while IFS='' read -r -d '' fname ; do
        echo "$fname"
done < <( find . -depth -type f -name '*.mp3' -print0 )

Finally, and I should've mentioned this yesterday, there are a multitude of batch renaming options available, and an unbelievable number of previous discussions on this same topic. If you want to know more, just do a bit of searching in the archives or the web.

the problem with the above script is that it uses bash:
done < <( find . -depth -type f -name '*.mp3' -print0 )

Your inputs are welcome

Sh could do it one day, would be useful. All my init.d script are based on sh that I employ mostly. I try to stick to sh for minimal install. dont really know why.


All times are GMT -5. The time now is 05:54 AM.