find
You can use find
command with -execdir
that will execute command of your choice in a directory where file matching pattern is:
find data -type f -name '*.txt' -execdir mv \{\} notes.txt \;
data
is path to directory where find
should look for matching files recursively
-type f
look only for files, not directories
-name '*.txt'
match anything that ends with .txt
-execdir mv \{\} notes.txt
run command mv {} notes.txt
in directory where file was found; where {}
is original filename found by find
.
bash
EDIT1: To do this without find
you need to handle recursive directory traversal (unless you have fixed directory layout). In bash
you can set following shell options with shopt -s
command:
extglob
- extended globbing support (allows to write extended globs like **
; see "Pathname Expansion" in man bash
)
globstar
- allows **
in pathname expansion; **/
will match any directories and their subdirectories (see "Pathname Expansion" in man bash
).
nullglob
- allows patterns that match no files (in case there's a directory without any .txt file)
Following script will traverse directories under data/
and rename .txt files to notes.txt
:
#!/bin/bash
shopt -s extglob globstar nullglob
for f in data/**/*.txt ; do
mv $f $(dirname $f)/notes.txt
done
mv $f $(dirname $f)/notes.txt
moves (renames) file; $f
contains matched path so e.g. data/folder1/day4notes.txt
and $(dirname $f)
gets directory where that file is - in this case data/folder1
so we just append /notes.txt
to that.
EDIT2: If you are absolutely positive that you want to do this only in first level of subdirectories under data/
you can omit extglob
and globstar
(and if you know there's at least one .txt in each directory then also nullglob
) and go ahead with pattern you posted; but you still need to use mv $f $(dirname $f)/notes.txt
to rename file.
NOTE: When experimenting with things like these always make backup beforehand. If you have multiple .txt files in any of directories they all will get renamed to notes.txt
so you might lose data in that case.