LinuxQuestions.org
Register a domain and help support LQ
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 11-24-2015, 06:23 PM   #1
maples
Member
 
Registered: Oct 2013
Location: IN, USA
Distribution: Arch, Debian Jessie
Posts: 810

Rep: Reputation: 264Reputation: 264Reputation: 264
Getting part of a filename


Hi,
I've got a bunch of files that I want to resize and rename. I'm confident that I can get the resizing working, but I'm stumped on the renaming.

First, here are some of the filenames:
Code:
Addison_6052794_71010640.jpg
Adirondack_6043462_71009100.jpg
Alden_71012337 copy.jpg
Almond_6045535_(397)_71009692.jpg
I want to rename them to just the number starting with a 7. So the first one would become 71010640.jpg.

I've done some looking around, and to be honest I'm a little lost and a little overwhelmed. I've seen lots of things saying to use awk, sed, and perl, but none of what I've tried has worked.

Code:
ls | awk '/.7\d{7}./'
ls | awk '/.7\d{7}./{print $0}'
ls | awk '/.+7\d{7}.+/{print $0}'
ls | awk '/.+7\d{7}.+/'
ls | awk '/.+7\d{7}.+/{print $1}'
ls | perl -n -e'/test(.+7\d{7}.+)/ && print $1'
ls | perl -n -e'/test(".+7\d{7}.+")/ && print $1'
Are any of these close, or am I completely off track?

Thanks
 
Old 11-24-2015, 07:38 PM   #2
LanceTaylor
Member
 
Registered: Nov 2015
Location: Houston, Texas, US
Distribution: RHEL/CentOS, Debian/Linux Mint, SLES
Posts: 40

Rep: Reputation: 19
The following worked on my system using the sample filenames that you provided:
Code:
ls | sed -ne 's/^.*71/71/' -e 's/\(71[0-9]*\).*/\1/p' | awk '{print $0".jpg"}'
 
1 members found this post helpful.
Old 11-24-2015, 07:52 PM   #3
berndbausch
Senior Member
 
Registered: Nov 2013
Location: Tokyo
Distribution: Redhat/Centos, Ubuntu, Raspbian, Fedora
Posts: 1,687

Rep: Reputation: 353Reputation: 353Reputation: 353Reputation: 353
Quote:
Originally Posted by maples View Post
Addison_6052794_71010640.jpg
Adirondack_6043462_71009100.jpg
Alden_71012337 copy.jpg
Almond_6045535_(397)_71009692.jpg
If there is an underscore immediately before the 7, and no underscore anywhere after the 7, you can use the shell's built-in parameter expansion.

Code:
FILENAME="Addison_6052794_71010640.jpg"
echo ${FILENAME##*_}
This means: Remove the longest possible string from FILENAME that ends in an underscore.

If this condition is not given, you can use a more general pattern matching and replacement construct like
Code:
${parameter/pattern/string}

Last edited by berndbausch; 11-24-2015 at 07:53 PM.
 
2 members found this post helpful.
Old 11-24-2015, 10:16 PM   #4
maples
Member
 
Registered: Oct 2013
Location: IN, USA
Distribution: Arch, Debian Jessie
Posts: 810

Original Poster
Rep: Reputation: 264Reputation: 264Reputation: 264
Thanks for the replies!

Quote:
Originally Posted by LanceTaylor View Post
Code:
ls | sed -ne 's/^.*71/71/' -e 's/\(71[0-9]*\).*/\1/p' | awk '{print $0".jpg"}'
Would you mind elaborating on what's happening with this? It looks to me like sed is removing everything before a "71" and then cutting off anything that's not a digit from the end. At the end of the second expression, what does the "p" do? (Or, what is that trailing letter called so I know what to look for?)

As for working, this catches most of the ones where the number starts with 71. However, for something like "Warfield_71007157_Inset.jpg" it just gives "7157.jpg", whereas I need the full name.

I probably should have mentioned explicitly that the number I want will always be 8 digits long and begin with a 7.

I tried several variants of
Code:
ls | sed -ne 's/^.*7[0-9]*/7/' -e 's/\(7[0-9]*\).*/\1/p' | awk '{print $0".jpg"}'\
ls | sed -ne 's/^.*7[0-9]*/7[0-9]*/' -e 's/\(7[0-9]*\).*/\1/p' | awk '{print $0".jpg"}'
but those didn't work.

Quote:
Originally Posted by berndbausch View Post
If there is an underscore immediately before the 7, and no underscore anywhere after the 7, you can use the shell's built-in parameter expansion.

Code:
FILENAME="Addison_6052794_71010640.jpg"
echo ${FILENAME##*_}
This means: Remove the longest possible string from FILENAME that ends in an underscore.
I never thought that the shell itself would have the needed pattern matching, so this is really interesting. But what about if there's something after the number, like "Alden_71012337 copy.jpg"? Will the " copy.jpg" get added on as well?

Quote:
If this condition is not given, you can use a more general pattern matching and replacement construct like
Code:
${parameter/pattern/string}
I will need to look into this further. Again, I wasn't aware that shells had this much built in to them!

Thanks again.

EDIT: Using slight variations of LanceTaylor's suggestion (making the number it searched for more precise and running it a few times) I was able to accomplish what I needed, so I'm marking this thread as solved. However, I'd like to learn more about this, so by all means please contribute your thoughts.

Last edited by maples; 11-24-2015 at 10:33 PM.
 
Old 11-25-2015, 12:32 AM   #5
berndbausch
Senior Member
 
Registered: Nov 2013
Location: Tokyo
Distribution: Redhat/Centos, Ubuntu, Raspbian, Fedora
Posts: 1,687

Rep: Reputation: 353Reputation: 353Reputation: 353Reputation: 353
Quote:
Originally Posted by maples View Post
I never thought that the shell itself would have the needed pattern matching, so this is really interesting. But what about if there's something after the number, like "Alden_71012337 copy.jpg"? Will the " copy.jpg" get added on as well?
The shell's text processing capabilities have become very powerful over the years, to an extent that it violates the old UNIX principle that a program should do one thing and do it well. No need to compete against awk and sed, in my opinion. But of course, it can be convenient.

The pattern that I used "*_" means "any string followed by an underscore". The "##" operator therefore deletes any string followed by an underscore from the beginning. Whatever comes after the underscore is not deleted, no matter what characters it contains.

By the way, since it's a double hash, the longest possible match will be deleted; the single hash operator "#" deletes the shortest possible match.
 
2 members found this post helpful.
Old 11-25-2015, 01:02 AM   #6
LanceTaylor
Member
 
Registered: Nov 2015
Location: Houston, Texas, US
Distribution: RHEL/CentOS, Debian/Linux Mint, SLES
Posts: 40

Rep: Reputation: 19
Quote:
Originally Posted by maples View Post
Would you mind elaborating on what's happening with this? It looks to me like sed is removing everything before a "71" and then cutting off anything that's not a digit from the end. At the end of the second expression, what does the "p" do? (Or, what is that trailing letter called so I know what to look for?)
The p is telling sed to print what it is holding in its active pattern space.

Here is a revised command line to meet your requirements:
Code:
for file in *copy.jpg; do mv "$file" "${file//[[:space:]]copy}"; done; ls *.jpg | sed -ne 'p;s/^.*\(7[0-9][0-9][0-9][0-9][0-9][0-9][0-9]\)/\1/p' | xargs -n2 mv
The for loop removes the " copy" from the end of those files that have it.
Then we list all of the .jpg files and pass that to sed which prints the original filename, then prints another name that only has the 7 followed by 7 additional digits. These two names are then passed to the mv command with xargs.
 
1 members found this post helpful.
Old 11-25-2015, 02:48 AM   #7
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,243

Rep: Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684
Code:
#!/usr/bin/env bash

regex='_(7[0-9]{7})'

for f in *.jpg
do
  [[ "$f" =~ $regex ]] || continue

  echo mv "$f" "${BASH_REMATCH[1]}.jpg"
done
When happy with results, just remove the echo and the action will happen
 
1 members found this post helpful.
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
to extract all the part of the filename before a particular word in the filename aealexanderraj Programming 1 08-27-2012 12:08 PM
Remove a part from a filename mainstream Linux - Newbie 10 03-29-2011 08:27 PM
replacing part of filename berrance Linux - Newbie 9 04-25-2010 11:10 AM
Extracting part of a filename wtaicken Programming 7 01-02-2009 09:01 AM


All times are GMT -5. The time now is 10:39 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
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration