0

I'm still new to the shell and need some help.

  1. I have a file stapel_old.
  2. Also I have in the same directory files like english_old_sync, math_old_sync and vocabulary_old_sync.

The content of stapel_old is:

english  
math  
vocabulary

The content of e.g. english is:

basic_grammar.md  
spelling.md  
orthography.md

I want to manipulate all files which are given in stapel_old like in this example:

  1. take the first line of stapel_old 'english', (after that math, and so on)
  2. convert in this case english to english_old_sync, (or after that what is given in second line, e.g. math to math_old_sync)
  3. search in english_old_sync line by line for the pattern '.md'
  4. And append to each line after .md :::#a1

The result should be e.g. of english_old_sync:

basic_grammar.md:::#a1
spelling.md:::#a1  
orthography.md:::#a1

of math_old_sync:

geometry.md:::#a1
fractions.md:::#a1

and so on. stapel_old should stay unchanged.

How can I realize that? I tried with sed -n, while loop (while read -r line), and I'm feeling it's somehow the right way - but I still get errors and not the expected result after 4 hours inspecting and reading.
Thank you!

EDIT
Here is the working code (The files are stored in folder 'olddata'):

clear
echo -e "$(tput setaf 1)$(tput setab 7)Learning directories:$(tput sgr 0)\n"
# put here directories which should not become flashcards, command: | grep -v 'name_of_directory_which_not_to_learn1' | grep -v 'directory2'
ls ../ | grep -v 00_gliederungsverweise | grep -v 0_weiter | grep -v bibliothek | grep -v notizen | grep -v Obsidian | grep -v z_nicht_uni | tee olddata/stapel_old

# count folders
echo -ne "\nHow much different folders: " && wc -l olddata/stapel_old | cut -d' ' -f1 | tee -a olddata/stapel_old
echo -e "Are this learning directories correct? [j ODER y]--> yes; [Other]-->no\n"
read lernvz_korrekt
if [ "$lernvz_korrekt" = j ] || [ "$lernvz_korrekt" = y ];
then
    read -n 1 -s -r -p "Learning directories correct. Press any key to continue..."
else
    read -n 1 -s -r -p "Learning directories not correct, please change in line 4. Press any key to continue..."
    exit
fi
echo -e "\n_____________________________\n$(tput setaf 6)$(tput setab 5)Found cards:$(tput sgr 0)$(tput setaf 6)\n"


#GET && WRITE FOLDER NAMES into olddata/stapel_old
anzahl_zeilen=$(cat olddata/stapel_old |& tail -1)

#GET NAMES of .md files of every stapel and write All to 'stapelname'_old_sync
i=0
name="var_$i"

for (( num=1; num <= $anzahl_zeilen; num++ ))
do
    i="$((i + 1))"
    name="var_$i"
    name=$(cat olddata/stapel_old | sed -n "$num"p)
    find ../$name/ -name '*.md' | grep -v trash | grep -v Obsidian | rev | cut -d'/' -f1 | rev | tee olddata/$name"_old_sync"
done
(tput sgr 0)

I tried to add:

input="olddata/stapel_old"
while IFS= read -r line
do
    sed -n "$line"p olddata/stapel_old
done < "$input"

The code to change only the english_old_sync is:

lines=$(wc -l olddata/english_old_sync | cut -d' ' -f1)
for ((num=1; num <= $lines; num++))
do
    content=$(sed -n "$num"p olddata/english_old_sync)
    sed -i "s/"$content"/""$content":::#a1/g"" olddata/english_old_sync
done

So now, this need to be a inner for-loop, of a outer for-loop which holds the variable for english, right?

starball
  • 20,030
  • 7
  • 43
  • 238
pingu
  • 11
  • 3
  • 1
    Show your code please so someone can help over it – LMC Sep 11 '21 at 16:38
  • Start with a simpler problem. Can you write a sed command that will modify `english_old_sync` the way you want? – Beta Sep 11 '21 at 16:40
  • Thank you both. I edited my question with the code I have. @Beta Sorry, I can't because I need to read first the first entry of 'stapel_old' and than use sed. And I don't really know how to combine it. I posted the tried sed command in my edited question. Thank you. – pingu Sep 11 '21 at 17:06
  • @Beta oh, I'm sorry I missunderstood. So the code, to change only english_old_sync is now written in my post, too. – pingu Sep 11 '21 at 17:29

1 Answers1

0

stapel_old should stay unchanged.

You could try a while + read loop and embed sed inside the loop.

#!/usr/bin/env bash

while IFS= read -r files; do
  echo cp -v "$files" "${files}_old_sync" &&
  echo sed '/^.*\.md$/s/$/:::#a1/' "${files}_old_sync"
done < olddata/staple_old

convert in this case english to english_old_sync, (or after that what is given in second line, e.g. math to math_old_sync)

  • cp copies the file with a new name, if the goal is renaming the original file name from the content of the file staple_old then change cp to mv

  • The -n and -i flag from sed was ommited , include it, if needed.

  • The script also assumes that there are no empty/blank lines in the content of staple_old file. If in case there are/is add an addition test after the line where the do is.

    [[ -n $files ]] || continue

  • It also assumes that the content of staple_old are existing files. Just in case add an additional test.

    [[ -e $files ]] || { printf >&2 '%s no such file or directory.\n' "$files"; continue; }


Or an if statement.

if [[ ! -e $files ]]; then
   printf >&2 '%s no such file or directory\n' "$files"
   continue
fi

  • See also help test

  • See also help continue


Combining them all together should be something like:

#!/usr/bin/env bash

while IFS= read -r files; do
  [[ -n $files ]] || continue
  [[ -e $files ]] || {
     printf >&2 '%s no such file or directory.\n' "$files"
     continue
  }
  echo cp -v "$files" "${files}_old_sync" &&
  echo sed '/^.*\.md$/s/$/:::#a1/' "${files}_old_sync"
done < olddata/staple_old

  • Remove the echo's If you're satisfied with the output so the script could copy/rename and edit the files.
Jetchisel
  • 7,493
  • 2
  • 19
  • 18
  • `sed` knows full well how to read lines from a file. Adding a newline between the commands is slightly sensitive to portablility issues, but you can use a semicolon instead if that's a problem. See also [Bash `while read` loop extremely slow compared to `cat`, why?](https://stackoverflow.com/questions/13762625/bash-while-read-loop-extremely-slow-compared-to-cat-why) – tripleee Sep 11 '21 at 17:48
  • @tripleee, I don't understand why the `cat` is needed. Also the new line you're referring is the line after the `&&` ? – Jetchisel Sep 11 '21 at 17:54
  • 1
    I mean you could replace the `while read` loop with a `sed` script, too, for reasons which are explained as in the linked question. You should not need `cat` here, the other question just uses it as a benchmark for timing. – tripleee Sep 11 '21 at 18:25
  • I would certainly want to know how to rename the files inside the `sed` script. – Jetchisel Sep 11 '21 at 23:12