3

Say I have a directory structure that is like Parent_dir/<name>/<date>/

How can I use a bash script placed into Parent_dir to navigate through every /<name>/<date>/ subdirectory and create a blank text file named <name>_<date>.txt within /<name>/<date>/ subdirectory?

Austin
  • 231

3 Answers3

4

From the Parent_dir:

for d in */*/; do f=${d/\//_}; touch -- "$d"/"${f::-1}.txt"; done

Note that touch will change the timestamp of any existing file.

You can do a dry-run first with replacing touch with echo:

for d in */*/; do f=${d/\//_}; echo -- "$d"/"${f::-1}.txt"; done
  • for d in */*/ lets us iterating over the directories two levels deep

  • f=${d/\//_} replaces first directory separator / with _ and save the output as variable f

  • "$d"/"${f::-1}.txt" expands to the directory name, followed by the desired filename; ${f::-1} strips off the last / from variable f

Note that, as the directory separator / is present with variable d, the / in "$d"/"${f::-1}.txt" is redundant; as almost all systems take // as single /, this should not be a problem. Alternately, you can drip /:

for d in */*/; do f=${d/\//_}; touch -- "${d}${f::-1}.txt"; done
heemayl
  • 56,300
  • Thanks! I'll try this out later because it looks very clean although the first post seemed to work for my needs :) – Austin Apr 09 '17 at 04:29
2

If you want the filenames to literally be named name_date.txt, try this:

#!/bin/bash
for dir in $(find . -maxdepth 2 -mindepth 2 -type d)
do
    touch "$dir"/name_date.txt
done

If you want the filenames to be <name>_<date>.txt, do this instead:

#!/bin/bash
IFS=$'\n'
for dir in $(find . -maxdepth 1 ! -path . -type d)
do
    for subdir in $(find "$dir" -mindepth 1 -type d)
    do
        base_dir=$(basename $dir)
        base_subdir=$(basename $subdir)

        touch "$base_dir"/"$base_subdir"/"$base_dir"_"$base_subdir".txt
    done
done
Tal
  • 2,112
1
find . -type d -exec sh -c '
   case ${1//[!\/]/} in
      "//" ) f=${1:2}; f=${f/\//_}; :> "$1/$f.txt" ;;
      * ) false ;;
   esac
' {} {} \; -prune

for d in */*/; do
   f=${d/\//_}
   :> "${d%?}/${f%?}.txt"
done
  • Rakesh buddy, please add some explanation to your posts as they keep showing up in the Low Quality Post review queue due to the fact there's only code and no text (I just had to review three of them)... – don_crissti Apr 09 '17 at 09:21