Reputation: 11
I have a folder with many sub folders nested inside of with images with the name such as "IMG_7729-300x300.jpeg¦IMG_7729-300x300.jpeg". I am trying to find a way using linux to delete all text before the | and including it.
I tried using this but was unable to get it to work
find . -type f -name "*|*" -exec bash -c 'f="$1"; g="${f/*|/}"; mv -- "$f" "$g"' | '{}' \;
Upvotes: 1
Views: 1147
Reputation: 181
I had a similar need, to rename a large number of files in order to remove a particular word from each filename. In my case I wanted to change the string "sidekiq_job" to just "job" for each file.
The solution I ended up finding most intuitive was a combination of find
, a for
loop, and sed
:
for filename in $(find ./app/jobs -type f -name '*sidekiq_job.rb'); do
mv "$filename" $(echo "$filename" | sed s/sidekiq_//g)
done
I've always found awk
's syntax a little hard to grok, so I like the ability to compose a few simple tools in this way.
Obviously you could use sed
to replace the problematic string with whatever you want.
Hopefully someone finds that useful.
Upvotes: 0
Reputation: 84521
You can use awk
to do it simply as well if you lack a POSIX shell (most are). With awk
you can simply use '¦'
as the field-separator FS
and the system command to move the file to a name comprised of the second field only, e.g.
$ls -1 *.jpeg | awk -F¦ '{cmd="mv "$1FS$2" "$2; system(cmd)}' -
Where you simply pipe the output of ls -1
(that's "dash one" not "dash lowercase L"). The cmd
is just a string concatenation creating the string mv $1¦$2.jpeg $2.jpeg
. (where FS
is used for '¦'
) The system()
command simply passes that to the shell. You can adjust the file glob as desired to meet your needs if you have names ending in other than .jpeg
, etc.
The result it it would take a directory containing:
$ ls -al
total 24
drwxr-xr-x 3 david david 4096 Jan 9 21:56 .
drwxr-xr-x 6 david david 4096 Nov 18 03:45 ..
drwxr-xr-x 2 david david 4096 Jan 9 21:56 orig
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7721-300x300.jpeg¦IMG_7721-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7722-300x300.jpeg¦IMG_7722-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7723-300x300.jpeg¦IMG_7723-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7724-300x300.jpeg¦IMG_7724-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7725-300x300.jpeg¦IMG_7725-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7726-300x300.jpeg¦IMG_7726-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7727-300x300.jpeg¦IMG_7727-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7728-300x300.jpeg¦IMG_7728-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7729-300x300.jpeg¦IMG_7729-300x300.jpeg
-rw-r--r-- 1 david david 115 Oct 17 2021 f1
-rw-r--r-- 1 david david 117 Oct 17 2021 f2
-rw-r--r-- 1 david david 117 Oct 17 2021 f3
and move the filenames as desire resulting in the contents:
$ ls -al
total 24
drwxr-xr-x 3 david david 4096 Jan 9 22:00 .
drwxr-xr-x 6 david david 4096 Nov 18 03:45 ..
drwxr-xr-x 2 david david 4096 Jan 9 21:56 orig
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7721-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7722-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7723-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7724-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7725-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7726-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7727-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7728-300x300.jpeg
-rw-r--r-- 1 david david 0 Jan 9 21:53 IMG_7729-300x300.jpeg
-rw-r--r-- 1 david david 115 Oct 17 2021 f1
-rw-r--r-- 1 david david 117 Oct 17 2021 f2
-rw-r--r-- 1 david david 117 Oct 17 2021 f3
Note: if you do have bash or shell allowing redirection from a subshell, you can eliminate the pipe using <(ls -1 *.jpeg)
, e.g.
awk -F¦ '{cmd="mv "$1FS$2" "$2; system(cmd)}' <(ls -1 *.jpeg)
(same result)
Using perl-rename
You can also use perl-rename
(often symlinked to rename
-- you can check which you have with rename --version
). You will either see something like "perl-rename 1.11"
or "rename from util-linux 2.38.1"
)
With perl-rename
you can use a simple substitute form s/find/replace/
using extended-REGEX to accomplish the removal of the first part of the filename. In your case that would be:
$ perl-rename 's/^[^¦]+¦//' *.jpeg
Where the find is ^[^¦]+¦
:
'^'
anchored from the beginning of line[^¦]+
select one-or-more characters not containing a '¦'
'¦'
And then replace with (nothing).
That will accomplish the same results as the awk
command above. The same caveat applies, adjust the file-glob as needed to operate on the desired files. You can also use the -n
option (--just-print
, --dry-run
) to see what would be renamed first without actually doing to rename to make sure you will accomplish your desired goal.
Upvotes: 0
Reputation: 103694
Use bash string manipulation and a glob:
touch "IMG_7729-300x300.jpeg¦IMG_7729-300x300.jpeg"
echo "before:"
ls
for fn in *¦*; do
mv "$fn" "${fn##*¦}"
done
echo "after:"
ls
If you want to use find
this is the best approach:
find . -type f -name "*¦*" -execdir bash -c 'fn="{}"; mv "$fn" "${fn##*¦}"' \;
With the -execdir
primary, find executes the command in the directory where the file is found. You don't, therefor, need to deal with the qualifying path before the base filename.
Upvotes: 0