Renaming only a particular string in a filename recursively - linux

I have a directory with 90 files. The file name is like
/user/jk/2016d/IDPSRU20160219_2345.txt
I want to change the filename to /user/jkris03/2016d/IDPSRU20160223_2345.txt
Please note that only 19 is replaced with 23 in the filename and the subsequent _2345 will be different for each file.
I would appreciate very much if you could provide the answer.
Please note that, the direcory/files are in hdfs.
Thanks,

If you just want to replace 19_ with 23_, you can do something like this:
hdfs dfs -ls -C /user/jk/2016d/ | awk '{OLD=$0; sub("19_", "23_", $0); system("hdfs dfs -mv "OLD" "$0);}'
where,
hdfs dfs -ls -C /user/jk/2016d/ : is for listing the HDFS files
OLD=$0 : is for storing the old file name
sub("19_", "23_", $0) : is for creating new file name
system("hdfs dfs -mv "OLD" "$0) : is for renaming the file
Hope it helps!

You can have a look at the rename command. It allows you to rename by regex. I think it differs between different distributions, so use man rename to see how it works for you.

Related

Recursively appending names of all files in a directory with exif specific png meta data field (aesthetic_score) with linux / EXIFtool

I am trying to rename all files located in a directory (recursively) with a specific meta data field appended to the end of the png file name.
the meta data field name is "aesthetic_score" with a value range from 1.0-9.0
when I type:
exiftool -Aesthetic_score -G1 -s testn.png
the result is:
[PNG] Aesthetic_score : 7.0
This is how I would like to append the png files recursively within a directory.
Note i would like to swap out the word aesthetic with the word chad in the append, and not all files will have this data field:
input file:
filename001.png (metadata aesthetic_score:7.0)
output:
filename001-chad-score-70.png
I tried to use Digikam and JExifToolGui-2.01, without success.
I am trying to perform this task in the cmd line, although other solutions are welcome. Thank you for your help.
So, this might work for you, I can't really test it; note that you would need to get rid of the echo before the mv for it to actually do something (rename rather than just show what it would do).
while read name
do
newname=$(exiftool -G1 -s "$name"|awk '$2~/FileName/{name=$4}; $2~/Aesthetic_score/{basename=gensub(/^(.+)\....$/,"\\1","1",name);ext=gensub(/^.*\.(...)$/,"\\1","1",name);gsub(/\./,"",$4);print basename"."$4"."ext}')
echo mv "$name" "$newname"
done <<<$( find -iname \*.png )
Basically the find at the very end finds all the pngs.
The while loop takes every name find throws it, and passes each file through exiftool (using your specs) and parses the output using awk, which then outputs the new name, which gets captured in the shell variable by the same name.
And finally the mv (without the echo) renames the files.

Like a vlookup but in bash to match filenames in a directory against a ref file and return full description

I am aware there isn't a special bash function to do this and we will have to build this with available tools -- e.g. sed, awk, grep, etc.
We dump files into a directory and while their filename looks random, they can be mapped to their full description. For example:
/tmp/abcxyz.csv
/tmp/efgwaz.csv
/tmp/mnostu.csv
In filemapping.dat, we have:
abcxyz, customer_records_abcxyz
efgwaz, routernodes_logs_efgwaz
mnostu, products_campaign
We need to go through each of them in the directory recursively and rename the file with its full description. Final outcome:
/tmp/customer_records_abcxyz.csv
/tmp/routernodes_logs_efgwaz.csv
/tmp/products_campaign_mnostu.csv
I found something similar here but not sure how to work it out at directory level dealing with only one file as the lookup/referece file. Please help. Thanks!
I would try something like this:
sed 's/,/.csv/;s/$/.csv/' filemapping.dat | xargs -n2 mv
Either cd to tmp beforehand, or modify the sed command to include the path name.
The sed commands simply replace the comma and the line end with the string ".csv".

Is there a way to undo a batch-rename of file extensions?

Ok so I kinda dropped the ball. I was trying to understand how things work. I had a few html files on my computer that I was trying to rename as txt files. This was strictly a learning exercise. Following the instructions I found here using this code:
for file in *.html
do
mv "$file" "${file%.html}.txt"
done
produced this error:
mv: rename *.html to *.txt: No such file or directory
Long story short I ended up going rogue and renaming the html files, as well as a lot of other non html files as txt files. So now I have files labeled like
my_movie.mp4.txt
my_song.mp3.txt
my_file.txt.txt
This may be a really dumb question but.. Is there a way to check if a file has two extensions and if yes remove the last one? Or any other way to undo this mess?
EDIT
Doing this find . -name "*.*.txt" -exec echo {} \; | cat -b seems to tell me what was changed and where it is located. The cat -b part is not necessary but I like it. This still doesn't fix what I broke though.
I'm not sure if terminal can check for extensions "twice", but you can check for . in every name an if there's more than one occurence of ., then your file has more extensions. Then you can cut the extension off with finding first occurence of . in a string when going backwards... or last one if checking characters in string in a normal way.
I have a faster option for you if you can use python. You can strip the extension with:
for file in list_of_files:
os.rename(file,os.path.splitext(file)[0])
which can give you from your file.txt.txt your file.txt
Example:
You wrote that your command tells you what has changed, so just take those changed files and dump them into a file(path to file per line). Then you can easily run this:
with open('<path to list>') as f:
list_of_files = f.readlines()
for file in list_of_files:
os.rename(file.strip('\n'), os.path.splitext(file.strip('\n'))[0])
If not, then you'd need to get the list from python:
import os
results = []
for root, folder, filenames in os.walk(<your path to folder>):
for filename in filenames:
if filename.endswith('.txt.txt'):
results.append(os.path.join(root, filename))
With this you got a list of files ending with .txt.txt like this <your folder>\\<path_to_file>.
Get a path to your directory used in os.walk() without folder's name(it's already in list) so it'll be like this:
e.g. os.walk('/home/me/directory') -> path='/home/me/' and res is item already in a list, which looks like directory/...
for res in results:
path = '' # set the path here
file = os.path.join(path,r)
os.rename(file, os.path.splitext(file)[0])
Depending on what files you want to find change .txt.txt in if filename.endswith('...') to whatever you like and os.rename() will take file's name without extension which in your case means it strips the additional extension you don't want to have.

Shell script to change file name using for loop

I want to change file names in a folder in a way like this:
previous form new form
one-1 to VAS-M0001-001
one-2 to VAS-M0001-002
one-3 to VAS-M0001-003
one-4 to VAS-M0001-004
Can anyone please suggest me a good way to do that?
I would just use a simple loop:
for f in one-*; do mv one-$f VAS-M001-000$f; done
Of course, you can use printf to format the number better (if you have more than 9 files)
rename has such a functionality
[username#hostname aa]$ touch one-1 one-2 one-3 one-4
[username#hostname aa]$ ls
one-1 one-2 one-3 one-4
[username#hostname aa]$ rename one- VAS-M0001-000 one*
[username#hostname aa]$ ls
VAS-M0001-0001 VAS-M0001-0002 VAS-M0001-0003 VAS-M0001-0004

Shell script to use a list of filenames in a CSV to copy files from one directory to another

I have a list of files that I need to copy. I want to recursively search a drive and copy those files to a set location if that filename exists in the list. The list is a text file/
the text file would look something like this:
A/ART-FHKFX1.jpg
B/BIG-085M.jpg
B/BIG-085XL.jpg
L/LL-CJFK.jpg
N/NRT-56808EA.jpg
P/PFE-25.10.jpg
P/PFE-7/60.jpg
P/PFE-7L.20.jpg
P/PFE-8.25.jpg
P/PFE-9.15.jpg
P/PFE-D11.1.tiff
P/PFE-D11.1.tiff
P/PFE-D12.2.tiff
P/PFE-D12.2.tiff
using find will take a lot of time, try to use locate if possible.
what will happen when there's several matches? like searching for foo.bar and having a/foo.bar and also b/foo.bar what would you do in that case?
your csv seems to include a path, given the previous I'll assume those paths are actually valid from where the script is run so in that case just do this:
#!/bin/bash
while read path; do
cp "$path" "$1"
done
then call it like this:
teh_script /path/to/destination < csv-file.csv

Resources