LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   Shell rename with first 4 characters (https://www.linuxquestions.org/questions/linux-software-2/shell-rename-with-first-4-characters-802514/)

Steve W 04-17-2010 02:40 AM

Shell rename with first 4 characters
 
Is there any way for me to use the rename command to rename selected files (in Nautilus - which means I'd have to put the script into my /.gnome2/nautilus-scripts folder) to the first four characters of their current name? So if for instance I had a file called "d3c999cab6273bb86a9a62406993aa1f.doc", it would rename it to just "d3c9.doc", automatically?

Thanks, Steve

unSpawn 04-17-2010 04:26 AM

YMMV(VM), completely untested and I don't use the 'rename' command as you required. Maybe some script like:
Code:

#!/bin/sh
# According to http://g-scripts.sourceforge.net/faq.php:
echo -e "${NAUTILUS_SCRIPT_SELECTED_FILE_PATHS}"|awk 'BEGIN { FS = "\n" } { printf "\"%s\" ", $1 }'|sed -e s#\"\"##|while read FILE; do
 if [ "${FILE}" = "${FILE//./}" ]; then
  # Detected(weak) no extension:
  NEWFILE="${FILE:0:4}"
 else
  NEWEXT="${FILE//*.}"; NEWFILE="${FILE//.*/}"; NEWFILE="${NEWFILE:0:4}.${NEWEXT}"
 fi
 # Only if it doesn't already exist:
 [ -f "${NEWFILE}" ] || eval echo "mv ${FILE} ${NEWFILE}"
done


Steve W 04-18-2010 01:23 AM

Thanks, but cannot get it to work and cannot see anything obviously wrong, except "FI" instead of "IF" in one of the lines. Can you have a quick scan through please as Bash is not a language I am familiar with.

Thank you again.

Steve

unSpawn 04-18-2010 04:56 AM

Quote:

Originally Posted by Steve W (Post 3939033)
cannot get it to work

Does it return anything?


Quote:

Originally Posted by Steve W (Post 3939033)
cannot see anything obviously wrong, except "FI" instead of "IF" in one of the lines.

Script looks OK to me. The "fi" closes the earlier "if" so that's correct. Maybe ask the Nautilus folks?

H_TeXMeX_H 04-18-2010 06:33 AM

Try:

Code:

for i in *.doc; do mv "$i" "$(echo "$i" | cut -c 1-4).doc"; done

MTK358 04-18-2010 07:43 AM

The "fi" is not a mistake, it closes the block started by "if".

Code:

#!/bin/sh

# Stuff here gets executed

if command; then
        # Stuff here gets executed only if command returned 0
fi

# Stuff here gets executed


Steve W 04-18-2010 01:13 PM

Quote:

for i in *.doc; do mv "$i" "$(echo "$i" | cut -c 1-4).doc"; done
That works, thanks - but of course is limited by only working for the stated extension (doc) and in lower case only. The original, much longer script would work for any extension so it would be handy to also get that working if possible.

Quote:

The "fi" is not a mistake, it closes the block started by "if".
Ha! Well I told you I had little experience in this scripting language. I am more used to putting IF() {...} or IF ... ENDIF etc.

Quote:

Does it return anything?
No, there is no change to the selected file's name. Is there any way I could run it in a shell and "point" it at a file to rename, and it would return any applicable error messages?

Thanks everyone, Steve.

MTK358 04-18-2010 01:43 PM

An adaptation of H_TeXMeX_H's script:

(Note that I don't guarantee that it works, I'm also not too great at bash scripting)

Code:

for file in *.*; do # iterate over all files with a dot in their name, but not starting with a dot
        newname=$(put a command here that prints out the proper new filename)
        if [ -e "$newname" ]; then # if $filename exists
                echo 'error: file "'"$newname"'" already exists!'
        else
                mv "$file" "$newname"
        fi
done


MTK358 04-18-2010 01:59 PM

I was playing around and made this command, which will generate the right filename when placed in the script in my previous post in place of the red text:

Code:

echo "$file" | sed --regexp-extended 's:(.{1,4}).*(\.[^.]*):\1\2:'
So here's the script, with a few improvements:

Code:

#!/bin/bash

for file in *.*; do # iterate over all files with a dot in their name, but not starting with a dot
        newname=$(echo "$file" | sed --regexp-extended 's:(.{1,4}).*(\.[^.]*):\1\2:')
        if [ "$file" != "$newname" ]; then
                if [ -e "$newname" ]; then # if $filename exists
                        echo 'error: file "'"$newname"'" already exists!'
                else
                        mv "$file" "$newname"
                fi
        fi
done


MTK358 04-18-2010 02:02 PM

It appears to work:

Code:

$ ls
dfadsf88.f89d7.fad  fgsf804087r.testing  test123.doc
$ first4
$ ls
dfad.fad  fgsf.testing  test.doc


Steve W 04-19-2010 01:25 AM

Quote:

It appears to work
Yes it does - thank you very much!

Although it does rename all files in the current directory. Is there an easy change to make it just do the files I have selected? Sort of "for file in selection"? I have a different script that appears to indicate that "$@" means "selected files", but cannot get "for file in $@" to work...

Steve
Fussy bugger

catkin 04-19-2010 02:22 AM

Quote:

Originally Posted by Steve W (Post 3939961)
Is there an easy change to make it just do the files I have selected? Sort of "for file in selection"? I have a different script that appears to indicate that "$@" means "selected files", but cannot get "for file in $@" to work...

Yes, it's just a matter of changing the list given to the for command, as you have tried; the problem is with "$@" not expanding to what you are hoping for. How are you setting $@? It is $1, $2 ... or the arguments passed to a function as shown in this command prompt demo
Code:

c@CW8:~$ function fun {
> echo "fun: my args are $@"
> }
c@CW8:~$ fun foo bar
fun: my args are foo bar


Steve W 04-19-2010 02:48 AM

Well, I'm taking the $@ idea from a short ps2pdf script, that goes:

cd $NAUTILUS_SCRIPT_CURRENT_URI
for arg in $@
do
ps2pdf $arg
done

Its purpose, of course, is to activate ps2pdf for the currently selected file in Nautilus, without having to call up the shell and type "ps2pdf myfile.ps" manually. This script is used by just selecting the .ps file you have in Nautilus, then playing the script. However, is the very first line relevant here? Is its purpose to pass the currently selected filename to the script?

And, more importantly, can the "rename to first 4 chars" script in its current form handle looping around all currently selected filenames, i.e. multiple filenames in current selection rather than just one currently selected file?

I kinda want to do (I'll revert to a BASIC syntax here):

For Each file IN Nautilus.selection
(Reduce filename to 4 chars, while keeping extension)
End For

The previous script from MTK358 works perfectly, but it does For Each file IN Current_Directory, and there will be files in there that I don't want reduce to first_four_chars. The only alternative is to temporarily copy the target files in their own directory first, then play the script, then copy them back again. So the ability to perform the script only on the selected files would be handy.

Thank you for any help you can give!

Steve

bakdong 04-19-2010 03:00 AM

You should be able to substitute 'for file in *.*' with 'for file in $@' and then supply filenames on the command line as parameters, or you could put the filenames you want to process in a file, one per line, and then read from that file using 'while read file; do [commands go here]; done << filelist' or you could amend the pattern in the original (*.*) to reflect what you want to select (e.g. d*.doc)

MrCode 04-19-2010 03:11 AM

I'm no expert on bash scripting here, but I take it that "$@" is basically representative of the entire string of characters that comes after the script name on the command line? Does it include spaces? I was just thinking you could maybe use sed or awk or something to chop up the string in "$@" to pieces that are a bit more digestable by the rest of the script...?

Just my :twocents:

:scratch:


All times are GMT -5. The time now is 06:08 AM.