#!/bin/bash
# Iterate through each .jpg file in the current directory
for file in *.jpg; do
# Rename the file by adding "front" to the beginning of the name
mv "$file" "front-$file"
done
But after the command I keep getting the error No such file or directory
~/Music$ find . -name '*.jpg' | while read file; do ( mv "$file" "front-$file" ); done
mv: cannot move './dog.jpg' to 'front-./dog.jpg': No such file or directory
CodePudding user response:
The files returned by find .
command start with ./
token.
With mv "$file" "front-$file"
, destination files start with front-./
token.
mv
search a directory named front-.
. If it's not exists, the command exit with an error code and the associated message.
Replace "front-$file"
by "${file%/*}/front-${file##*/}"
.
Explanations:
${file%/*}
remove last right part (part are separated by a/
) of the filename${file##*/}
remove all parts from the left, except the last, of the filename
Example:
> file="./the/file/path/file.jpg"
> echo "${file%/*}/front-${file##*/}"
./the/file/path/front-file.jpg
CodePudding user response:
Your current find
solution will work for a top/root level directory, and produce the expected output by using basename
, something like:
find . -name '*.jpg' |
while IFS= read -r file; do
echo mv -- "$file" front-"$(basename -- "$file")"
done
It gets tricky when you have sub directories, because the *.jpg
files will be rename to the desired file name/output but it will also be move to the current directory where you ran/executed the find
command.
Consider this directory structure and *.jpg
files in them.
tmp/cat.jpg
tmp/fish panda.jpg
dog.jpg
Running your find
command against it would result in something like:
mv ./tmp/cat.jpg front-cat.jpg
mv ./tmp/fish panda.jpg front-fish panda.jpg
mv ./dog.jpg front-dog.jpg
A solution with Parameter Expansion for manipulating the path.
find . -name '*.jpg' |
while IFS= read -r file; do
file_name=${file##*/}; path_name=${file%/*};
mv -v -- "$file" "$path_name/front-$file_name"
done
A solution using -execdir
and basename
with a for
loop.
find . -name '*.jpg' -execdir sh -c '
for f; do mv -- "$f" front-"$(basename -- "$f")"; done' _ {}