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"' | '{}' \;
CodePudding user response:
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.
CodePudding user response:
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'¦'
- then select the
'¦'
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.