LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.

Notices


Reply
  Search this Thread
Old 04-17-2010, 02:40 AM   #1
Steve W
Member
 
Registered: Mar 2007
Distribution: Linux Mint 18.1
Posts: 520

Rep: Reputation: 44
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
 
Old 04-17-2010, 04:26 AM   #2
unSpawn
Moderator
 
Registered: May 2001
Posts: 29,415
Blog Entries: 55

Rep: Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600
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
 
1 members found this post helpful.
Old 04-18-2010, 01:23 AM   #3
Steve W
Member
 
Registered: Mar 2007
Distribution: Linux Mint 18.1
Posts: 520

Original Poster
Rep: Reputation: 44
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
 
Old 04-18-2010, 04:56 AM   #4
unSpawn
Moderator
 
Registered: May 2001
Posts: 29,415
Blog Entries: 55

Rep: Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600
Quote:
Originally Posted by Steve W View Post
cannot get it to work
Does it return anything?


Quote:
Originally Posted by Steve W View Post
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?
 
Old 04-18-2010, 06:33 AM   #5
H_TeXMeX_H
LQ Guru
 
Registered: Oct 2005
Location: $RANDOM
Distribution: slackware64
Posts: 12,928
Blog Entries: 2

Rep: Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301
Try:

Code:
for i in *.doc; do mv "$i" "$(echo "$i" | cut -c 1-4).doc"; done
 
1 members found this post helpful.
Old 04-18-2010, 07:43 AM   #6
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
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

Last edited by MTK358; 04-18-2010 at 07:45 AM.
 
Old 04-18-2010, 01:13 PM   #7
Steve W
Member
 
Registered: Mar 2007
Distribution: Linux Mint 18.1
Posts: 520

Original Poster
Rep: Reputation: 44
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.
 
Old 04-18-2010, 01:43 PM   #8
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
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

Last edited by MTK358; 04-18-2010 at 01:51 PM. Reason: More elegant way of checking if file exists
 
Old 04-18-2010, 01:59 PM   #9
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
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

Last edited by MTK358; 04-18-2010 at 02:05 PM.
 
1 members found this post helpful.
Old 04-18-2010, 02:02 PM   #10
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
It appears to work:

Code:
$ ls
dfadsf88.f89d7.fad  fgsf804087r.testing  test123.doc
$ first4
$ ls
dfad.fad  fgsf.testing  test.doc
 
1 members found this post helpful.
Old 04-19-2010, 01:25 AM   #11
Steve W
Member
 
Registered: Mar 2007
Distribution: Linux Mint 18.1
Posts: 520

Original Poster
Rep: Reputation: 44
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

Last edited by Steve W; 04-19-2010 at 01:41 AM.
 
Old 04-19-2010, 02:22 AM   #12
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by Steve W View Post
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
 
Old 04-19-2010, 02:48 AM   #13
Steve W
Member
 
Registered: Mar 2007
Distribution: Linux Mint 18.1
Posts: 520

Original Poster
Rep: Reputation: 44
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
 
Old 04-19-2010, 03:00 AM   #14
bakdong
Member
 
Registered: Apr 2009
Posts: 214

Rep: Reputation: 44
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)
 
Old 04-19-2010, 03:11 AM   #15
MrCode
Member
 
Registered: Aug 2009
Location: Oregon, USA
Distribution: Arch
Posts: 864
Blog Entries: 31

Rep: Reputation: 148Reputation: 148
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

 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
how to rename a file with weird characters in php michaeljoser Programming 4 06-29-2009 10:39 AM
Insert additional characters into filenames to rename them. Trap Linux - General 4 05-14-2009 06:25 AM
Rename files with the first three characters towards the end of the name pwc101 Programming 12 06-15-2008 06:25 PM
Rename a file with hexa decimal characters sandeshsk007 Linux - Software 13 12-13-2007 02:11 AM
rename file names with " ? characters fishbonz Linux - Newbie 2 05-31-2005 11:20 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software

All times are GMT -5. The time now is 11:30 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration