This question already has answers here:
remove date from filename but keep the file extension
(2 answers)
Closed 4 years ago.
Is there a quick and clever way to remove various timestamps from multiple files with different names? The timestamp format always remains the same, although the values differ. An example of my files would be...
A_BB_CC_20180424_134312
A_B_20180424_002243
AA_CC_DD_E_20180424_223422
C_DD_W_E_D_20180423_000001
with the expected output
A_BB_CC
A_B
AA_CC_DD_E
C_DD_W_E_D
Notice the last file has a different timestamp, I don't mind if this is a day specific timestamp removal or all, or two variations. My problem is I can't think of the code for an ever changing time value :(
Thanks in advance
EDIT - Adding edit in to show why this is not a duplicate as Tripleee thinks. His duplicate link is for files with the same prefix, my question is about files with different names so the answer is different.
Using parameter expansion %% bashism that removes the end of the filename:
for i in /my/path/*; do mv "$i" "${i%%_2018*}"; done
This relies on the timestamp that start with 2018...
Using awk:
for i in /my/path/*; do mv "$i" $(awk -v FS=_ 'NF-=2' OFS="_" <<< "$i"); done
This awk script is based on the field separator _. It prints the filename without the last 2 field representing the timestamp.
In order to rename a set of files and apply regular expressions in the renaming process you can use the rename command.
So in your example:
rename 's#_[0-9]*_[0-9]*##' *_[0-9]*
This renames all files in the current directory ending with _ followed by digits.
It cuts away all _ followed by digits followed by _ followed by digits.
Related
I have multiple GoPro files in a directory that all need to be renamed and would like a bash script to do it. Basically I want to move the 3rd and 4th characters back to the 12th and 13th spot with dashes around it. The only other GoPro post I found puts it at the end of the file but I really need it in the middle like that. Thank you
Example
Original filename is:
GX010112_1647792633961.MP4
and I need it to look like:
GX0112_164-01-7792633961.MP4
A possible answer with the rename command-line. It allows you to rename multiple files according to PERL regex.
#installation of rename
apt install rename
#rename your files
rename 's/^(.{2})(.{2})(.{8})(.*)/$1$3-$2-$4/' *
REGEX explanation:
The regex is structured as s/ MATCHING PATTERN / REPLACEMENT /
^: set position at the beginning of string.
(.{2}) : Match the first 2 characters and store it in $1.
(.{2}) : Match the following 2 characters (the 3th and 4th) and store it in $2.
(.{8}) : Match the following 8 characters (from the 5th to 12th included) and store it in $3.
(.*) : Match the rest of you string and store it in $4.
Hope it helps.
After many hours I figured it out based on this thread:
Rename several gopro files
for file in GX*; do
file1="${file#*??}"
file2=${file1#*??}
file3=${file1#*??????}
file4=${file1%*$file2}
file5=${file2%*?????????????????}
mv -v "$file" "${file5}${file4}${file3}"
done
I hope it comes in handy for any other GoProers out there!
This question already has answers here:
Difference between single and double quotes in Bash
(7 answers)
Closed 4 years ago.
I am very new to this all and have used this website to help me find the answers i'm looking for.
I want to replace a line in multiple files across multiple directories. However I have struggled to do this.
I have created multiple directories 'path_{0..30}', each directory has the same 'input' file, and another file 'opt_path_rx_00i.xyz' where i corresponds to the directory that the file is in (i = {0..30}).
I need to be able to change one of the lines (line 7) in the input file, so that it changes with the directory that the input file is in (path_{0..30}). The line is:
pathfile opt_path_rx_00i.xyz
Where i corresponds to the directory that the file is in (i={0..30})
However, i'm struggling to do this using sed. I manage to change the line for each input file in the respective directories, but i'm unable to ensure that the number i changes with the directory. Instead, the input file in each directory just changes line 7 to:
pathfile opt_path_rx_00i.xyz
where i, in this case, is the letter i, and not the numbers {0..30}.
I'll show what i've done below in order to make more sense.
for i in {0..30}
do
sed -i '7s/.*/pathfile-opt_path_rx_00$i.xyz/' path_$i/input
done
What I want to happen is, for example in directory path_3, line 7 in the input file will be:
pathfile opt_path_rx_003.xyz
Any help would be much appreciated
can you try with double quotes
for i in {0..30}; do
sed -i "7s/.*/pathfile-opt_path_rx_00$i.xyz/" "path_$i/input"
done
This question already has answers here:
How to change a command line argument in Bash?
(3 answers)
How to compare timestamp on files in bash scripting
(3 answers)
Closed 5 years ago.
I often use exiftool to copy metadata from one file to another.
exiftool -TagsFromFile FILE1[SOURCE] FILE2[TARGET]
I am trying to speed up the workflow and figure out a bash script that would allow me to simply select two files in file explorer - right click on them - open with - thescript.sh
/path/to/thescript.sh $1 $2
As you can see the most important part is to select a right file as the source ($1) / target ($2).
Source files often named like this:
20170630_181348_2674.jpg or 20170630_181348_2674.dng
Target files usually have a suffix added to the name e.g. 20170630_181348_2674_0001.jpg or 20170630_181348_2674_v2.jpg
So one thing I know for sure is that the source file name is always shorter.
Another thing, the files I use as the source are always older than the ones I copy metadata to.
I was wondering if there is any way in bash to compare inputs ($#) by their file name or by the file modify date and place them as $1 and $2 accordingly.
Any ideas would be greatly appreciated.
StackOverflow.
I have a colleciton of notes from work. I keep them as markdown files, and had been formatting them with the date and year - for example, today's is titled 06132017.md
I am coming up on a year at work, so I have quite a few of these files. I wish to change the naming convention from month/day first to year first, so that I can sort them alphabetically and easily find dates I need.
So 06132017.md would become 20170613.md - this would keep 2016 and 2017 from mixing in aplha order. Is there a command I can run on a folder to do this?
If you have the Perl rename utility, it's rather simple to do:
$ prename 's/^(....)(....)(\.md)$/$2$1$3/' *.md
06132017.md renamed as 20170613.md
The dots match any character, the parenthesis group, and $N on the replacement side inserts the characters captured in the groups.
Or just in Bash:
$ for x in ????????.md ; do mv -v "$x" "${x:4:4}${x:0:4}.md" ; done
'06132017.md' -> '20170613.md'
${var:n:m} takes a substring of length m, starting at position n from variable var.
This question already has answers here:
How to remove the lines which appear on file B from another file A?
(12 answers)
Closed 9 years ago.
I’ve got two text files, each with several hundred lines. Some of the lines exist in both files, and I want to remove those so that they exist in only one of the files. Basically, I want to reduce them to get a unique set of lines. The catch is that I can’t sort them (they are stripped-down dumps of my Chromium history).
What is the easiest way to do this?
I tried WinDiff, but that gave incorrect results. I figure that I could knock together a PHP script in a while, but am hoping that there is an easier way (preferably a command-line tool).
Well, I ended up writing a PHP script after all.
I read both files into a string, then exploded the strings into arrays using \r\n as the delimiter. I then iterated through the arrays to remove any elements that exist, and finally dumped them back out to a file.
The only problem was that by trying to refactor the stripping routine to a function, I found that passing the array that gets changed (elements removed) by reference caused it to slow down to the point of needing to be Ctrl-C’d, so I just passed by value and returned the new array (counterintuitive). Also, using unset to delete the elements was slow no matter what, so I just set the element to an empty string and skipped those during the dump.
If you have a bash shell (cygwin), the following shell commands would remove all lines that appear in both files from a.txt:
comm -12 <(sort a.txt|uniq) <(sort b.txt|uniq) | while read dupe; do dupe_escaped=$(echo "$dupe" | sed 's/[][\.*^$/]/\\&/g'); sed -e "/${dupe_escaped}/d" -i a.txt; done