Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

remove everything but the date

29 views
Skip to first unread message

mc

unread,
Apr 11, 2013, 8:23:24 AM4/11/13
to
Hi all,

I have several files in a folder. Each filename contains a date
occurrence in the format yyyyMMdd (eg. 20130401)

Using bash, how can I rename the files removing everything but the date?

For example:
"02file_20130401foo.txt" ---> "20130401.txt"

I don't need to verify the date, I know it is always valid and there is
just one occurrence of the pattern yyyyMMdd.

Thanks for your help,

mc.



Janis Papanagnou

unread,
Apr 11, 2013, 9:24:50 AM4/11/13
to
To be on the safe side using POSIX only code you can do

pat=[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]
for f in *${pat}*
do
pref=${f%${pat}*}
suff=${f#*${pat}}
ff=${f#${pref}}
ff=${ff%${suff}}
ext=${f##*.}
mv -i "$f" "${ff}.${ext}"
done

With a ksh93 and back-references you can do

for f in *${pat}*
do
mv -i "$f" "${f/*@(${pat})*.@(*)/\1.\2}"
done

Not sure whether the latter is supported by bash (with extglob set).

Janis

Thomas 'PointedEars' Lahn

unread,
Apr 11, 2013, 7:26:01 PM4/11/13
to
As you can see, this is non-trivial in a sh or ksh-compatible shell.
Why not use the right tool for the right job?

find . -name . -or -prune rename 's/^.*(\d{8}).*(\..+)?$/\1\2/' {} +

If you are sure about the date, you could specify further, to avoid false
positives:

find . -name . -or -prune rename 's/^.*(20\d{6}).*(\..+)?$/\1\2/' {} +

--
PointedEars

Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

Chris F.A. Johnson

unread,
Apr 12, 2013, 1:10:39 AM4/12/13
to
On 2013-04-11, Thomas 'PointedEars' Lahn wrote:
> mc wrote:
>
>> I have several files in a folder. Each filename contains a date
>> occurrence in the format yyyyMMdd (eg. 20130401)
>>
>> Using bash, how can I rename the files removing everything but the date?
>>
>> For example:
>> "02file_20130401foo.txt" ---> "20130401.txt"
>>
>> I don't need to verify the date, I know it is always valid and there is
>> just one occurrence of the pattern yyyyMMdd.
>
> As you can see, this is non-trivial in a sh or ksh-compatible shell.
> Why not use the right tool for the right job?
>
> find . -name . -or -prune rename 's/^.*(\d{8}).*(\..+)?$/\1\2/' {} +
>
> If you are sure about the date, you could specify further, to avoid false
> positives:
>
> find . -name . -or -prune rename 's/^.*(20\d{6}).*(\..+)?$/\1\2/' {} +

rename is not an operator in either POSIX or GNU find (unless it's a
very recent addition), nor is it a standard command (and there are
at least two versions in the wild with differing syntax).

--
Chris F.A. Johnson, author <http://shell.cfajohnson.com/>
===================================================================
Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress)
Pro Bash Programming: Scripting the GNU/Linux Shell (2009, Apress)

Thomas 'PointedEars' Lahn

unread,
Apr 12, 2013, 4:40:40 AM4/12/13
to
Chris F.A. Johnson wrote:

> On 2013-04-11, Thomas 'PointedEars' Lahn wrote:
>> mc wrote:
>>> I have several files in a folder. Each filename contains a date
>>> occurrence in the format yyyyMMdd (eg. 20130401)
>>>
>>> Using bash, how can I rename the files removing everything but the date?
>>>
>>> For example:
>>> "02file_20130401foo.txt" ---> "20130401.txt"
>>>
>>> I don't need to verify the date, I know it is always valid and there is
>>> just one occurrence of the pattern yyyyMMdd.
>>
>> As you can see, this is non-trivial in a sh or ksh-compatible shell.
>> Why not use the right tool for the right job?
>>
>> find . -name . -or -prune rename 's/^.*(\d{8}).*(\..+)?$/\1\2/' {} +
>>
>> If you are sure about the date, you could specify further, to avoid false
>> positives:
>>
>> find . -name . -or -prune rename 's/^.*(20\d{6}).*(\..+)?$/\1\2/' {} +
>
> rename is not an operator in either POSIX or GNU find (unless it's a
> very recent addition), nor is it a standard command (and there are
> at least two versions in the wild with differing syntax).

Should have (obviously) been

find . -name . -or -prune -exec rename 's/^.*(20\d{6}).*(\..+)?$/\1\2/' {} +

rename(1) comes with the Perl distribution (as a symlink to prename). That
does not preclude the possibility of using it; it might even be an argument
for using it. Which two versions are you talking about?

The approach can be adjusted to use sed(1) or awk(1) instead, POSIX-
compliant or not.

Chris F.A. Johnson

unread,
Apr 12, 2013, 11:28:46 AM4/12/13
to
The Perl version and this one:

$ file /usr/bin/rename
/usr/bin/rename: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped

Thomas 'PointedEars' Lahn

unread,
May 15, 2013, 5:12:38 PM5/15/13
to
Chris F.A. Johnson wrote:

> On 2013-04-12, Thomas 'PointedEars' Lahn wrote:
>> […]
>> rename(1) comes with the Perl distribution (as a symlink to prename).
>> That does not preclude the possibility of using it; it might even be an
>> argument for using it. Which two versions are you talking about?
>
> The Perl version and this one:
>
> $ file /usr/bin/rename
> /usr/bin/rename: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
> dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped

What would be the best way to tell them apart?
0 new messages