0

Looking for help with the following code. I have a folder titled data, with 6 subfolders (folder1, folder2, etc). Each folder has a text file I want to rename to "homeworknotes" keeping the .txt extension.

Used notes before for short:

So far I have the following code:

for file in data/*/*.txt; do
mv $file "notes"
done
  • Does this answer your question? [Rename all files in directory from $filename\_h to $filename\_half?](https://stackoverflow.com/questions/7450818/rename-all-files-in-directory-from-filename-h-to-filename-half) – maru Jan 28 '22 at 14:34

1 Answers1

4

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.

blami
  • 6,588
  • 2
  • 23
  • 31
  • @swampmonkey updated my answer to do it in bash loop; although I recommend you to stick with find when it comes to traversing directory structures. – blami Jan 28 '22 at 03:14