#!/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' _ {}
