Как добавить порядковые номера, скажем, 1,2,3 и т.д. к каждому имени файла, а также для каждой строки содержимого файла в каталоге?

#linux #bash #unix #ksh #sequential-number

#linux #bash #unix #ksh #порядковый номер

Вопрос:

Я хочу добавить порядковый номер для каждого файла и его содержимого в каталоге. Порядковый номер должен иметь префикс имени файла, и для каждой строки его содержимого должен иметь тот же номер с префиксом. Таким образом, порядковые номера должны быть сгенерированы для всех файлов (для имен и их содержимого) во вложенных папках каталога.

Я попытался использовать функцию maxdepth, rename, print как часть. но он выдает ошибку, в которой говорится, что «-maxdepth» — недопустимый параметр.

У меня уже есть часть кода (для печати имен и содержимого текстовых файлов в каталоге), и к нему должна быть добавлена эта логика.

 #!bin/bash
cd home/TESTING
for file in home/TESTING;
do
find home/TESTING/ -type f -name *.txt -exec basename {} ';' -exec cat {} ;
done
  

P.s — печать, переименование, максимальная глубина не работают

Если имя первого файла равно File1.txt и его содержимое упоминается как «Louis», тогда вывод для имени файла должен быть 1File1.txt и содержимое должно быть как «1Louis».То же самое следует заменить на 2 для второго файла. Таким образом, он должен пройти через все вложенные папки в каталоге и распечатать соответственно. У меня уже есть часть кода, и к нему следует добавить эту логику.

Ответ №1:

При выполнении cd в скрипте должна быть обеспечена отказоустойчивость. Вы можете выполнить команду в неправильном каталоге, если вы этого не сделаете.

При вашей попытке вывод будет таким же даже без цикла for, так как for file in home/TESTING передается home/TESTING только в качестве аргумента for , поэтому он запускается только один раз. В случае for file in home/TESTING/* это произошло бы иначе, как.

Я использовал find без --maxdepth , поэтому он также будет просматривать все подкаталоги для *.txt файлов. Если вы хотите, чтобы только текущий каталог $(find /home/TESTING/* -type f -name "*.txt") можно было заменить на $(ls *.txt) , пока у вас нет каталога, который заканчивается на .txt , проблем не будет.

 #!/bin/bash

# try cd to directory, do things upon success.
if cd /home/TESTING ;then
      # set sequence number
      let "x = 1"

      # pass every file to for that find matching, sub directories will be also as there is no maxdeapth.
      for file in $(find /home/TESTING/* -type f -name "*.txt") ; do

            # print sequence number, and base file name, processed by variable substitution. 
            # basename can be used as well but this is bash built in.
            echo "${x}${file##*/}"

            # print file content, and put sequence number before each line with stream editor.
            sed 's#^#'"${x}"'#g' ${file}

            # increase sequence number with one.
            let "x  "
      done

      # unset sequence number
      unset 'x'
else
      # print error on stderr
      echo 'cd to /home/TESTING directory is failed' >amp;2
fi
  

Замена переменной:

Есть еще кое-что, я выбрал только эти 4, поскольку они похожи.

${var#pattern} — Используйте значение var после удаления текста, соответствующего шаблону слева

${var##pattern} — То же, что и выше, но удалите самую длинную соответствующую часть вместо самой короткой

${var%pattern} — Используйте значение var после удаления текста, соответствующего шаблону справа

${var%%pattern} — То же, что и выше, но удалите самую длинную соответствующую часть вместо самой короткой

So ${file##*/} примет переменную $file и удалит каждый символ * до последней ## косой черты / . $file Значение переменной не изменяется этим, поэтому оно по-прежнему содержит путь и имя файла.

sed 's#^#'"${x}"'#g' ${file} sed — это редактор потоков, для этого конкретного есть целые книги о его использовании. Обычно он помещается в одинарные кавычки, поэтому 's#^#1#g' добавит 1 в начало каждой строки в файле. s это подстановка, ^ это начало файла, 1 это текст, g является глобальным, если вы не поместите туда g, это затронет только первый мач. # это разделитель, он может быть и другим, как / , например. Я отключил одинарную кавычку, чтобы разрешить использование переменной, и снова открыл одинарную кавычку.

Если вы хотите заменить текст, .txt на .php, вы можете использовать sed 's#.txt#.php#g' file , . имеют особое значение, они могут заменить любой отдельный символ, поэтому его нужно экранировать , чтобы использовать его как текст. остальное не только file.txt будет сопоставлено, но и file1txt также.

Это может быть передано по конвейеру, в этом случае вам не нужно указывать имя файла, иначе вы должны указать хотя бы одно имя файла, в нашем случае это была ${file} переменная, содержащая имя файла. Как я уже упоминал, подстановка переменных не изменяет значение переменной, поэтому она по-прежнему содержит имя файла с путем.

Комментарии:

1. Большое спасибо за ваш ответ. Я изменил x на x = x 1, так как столкнулся с некоторой проблемой с этим. Не могли бы вы, пожалуйста, объяснить мне эти команды (echo «$ {x}${file ##*/}» , sed ‘s # ^#'»${x}»‘# g’ $ {file}) подробно, если это возможно. Я пытаюсь это понять. Заранее спасибо.

2. Я обновил ответ, дайте мне знать, что-то неясно.

3. Большое вам спасибо за вашу помощь. Отличное объяснение! 🙂

4. Я допустил ошибку в примере sed. . может заменить любой символ, и в этом случае его необходимо экранировать.

5. да, спасибо. Я должен изменить код в соответствии с новым требованием. Я задам это как отдельный вопрос в stack overflow и представлю код, который я сделал для него. Я сталкиваюсь с некоторыми проблемами с этим. Если вы получаете уведомление об этом, пожалуйста, ответьте, если найдете время. Это просто запрос. То, как вы объясняете вещи, легко понять и кристально ясно. Большое вам спасибо за то, что помогли мне разобраться в этом