如何用两个命令编写 bash 脚本(在当前目录中递归查找并替换所有文件中的文本字符串)

如何用两个命令编写 bash 脚本(在当前目录中递归查找并替换所有文件中的文本字符串)

在 Ubuntu Server 上,我使用两个不同的命令在当前文件夹中递归地查找和替换所有文件中的字符串。

  1. 第一个命令是:

    sudo find . -type f -print0 |\
        xargs -0 -r sudo grep -F -l 'my-OLD-custom-string'
    

    此命令在当前文件夹中递归搜索所有文件并列出它们。它除了搜索和列出之外不执行任何其他操作,以便我可以验证这些是我想要更改的文件。一旦我验证列出的所有文件都是我想要将“my-OLD-custom-string”替换为“my-NEW-custom-string”的文件,我就可以继续执行第二个命令。

  2. 第二条命令是:

    sudo find . -type f -print0 |\
         xargs -0 -r sudo grep -F -l --null 'my-OLD-custom-string' |\
         xargs -0 -r sudo perl -pi~ -e 's/my-OLD-custom-string/my-NEW-custom-string/g'
    

    该命令会my-OLD-custom-string递归地在当前目录下的文件中查找“ ”,并将其替换为“ my-NEW-custom-string”,而将我原来未修改的文件保留为filename~,以便于恢复,以防万一。

我想将这些命令放入 bash 脚本中,以便它看起来读取/工作如下:

$ cd ~/Downloads
$ ls -la
total 40964
drwxrwxr-x  2 Danran Danran     4096 Mar  2 19:17 .
drwxr-x--- 20 Danran Danran     4096 Mar 13 15:02 ..
-rw-r--r--  1 Danran Danran 16380529 Sep 15 18:50 test_text1.txt
-rw-r--r--  1 Danran Danran      870 Feb 14 11:51 test_text2.txt
-rw-r--r--  1 Danran Danran     3129 Dec 22  2017 test_text3.txt
-rw-r--r--  1 Danran Danran    12693 Jan 20  2022 test_text4.txt
-rwxr-xr-x  1 Danran Danran        0 Mar 13 15:59 custom_bash_script.sh
$ cat test_text1.txt
my-OLD-custom-string
$ ./custom_bash_script.sh
Enter the text string you are searching for:
Text string here: my-OLD-custom-string
[sudo] password for Danran: ****************
Here are the listed files with your inputted text string:
./test_text1.txt
Would you like to replace the string "my-OLD-custom-string" in the above listed files?: y
What do you want the new string to be?: my-NEW-custom-string
The old string has now been replaced with the new string in the above requested files.
$ cat test_text1.txt
my-NEW-custom-string

这是我目前拥有的脚本,但它根本不起作用......

#!/bin/sh

echo "Enter the text string you are searching for:"
read -p "Text string here: " textstringold
sudo find . -type f -name "$textstringold"
sudo find . -type f -print0 |\
     xargs -0 -r sudo grep -F -l --null "$textstringold" |\
     xargs -0 -r sudo perl -pi~ -e "s/$textstringold/$textstringnew/g"

有人能帮我按照所需规格编写此脚本,以便它能按上述说明工作吗?任何帮助都将不胜感激!

答案1

该网站不是脚本编写网站,但帮助地球上的任何人是这个社区的强烈动机(不歧视来自其他星球的生物:-))。

也就是说,请将以下脚本作为模板/样板来帮助您开始,并且请不要要求改进,而是自己改进,或者如果必须的话提出一个新的单独问题......

#!/bin/bash

while read -r -p "You are in \"$PWD\". Is this the right directory? [y(es)|n(o)|q(uit): "; do
  case "$REPLY" in
    y) read -r -p "Pleas, enter the search string: "
       readarray -d '' files < <(grep -rF -l --null "$REPLY")
       if [[ "${#files[@]}" -eq 0 ]]; then
         printf '%s\n' "no matches found ... exiting"
         unset files
         exit
       else
         search="$REPLY"
         printf '%s\n' "${files[@]}" | less
         read -r -p "Matches found ${#files[@]}. Pleas, enter the replacement string: "
         replacement="$REPLY"
         printf '%s\0' "${files[@]}" |
         xargs -0 -r perl -p -e "s/${search}/${replacement}/g"
       fi
       unset files
       exit
       ;;
   n) while true; do
        read -r -p "Enter the correct directory path: "
        if ! [ -z "$REPLY" ]; then
          cd "$REPLY" && break
          fi
        done
        ;;
   q) exit
      ;;
   *) printf '%s\n' "Invalid input"
      ;;
  esac
done

您需要将其保存到文件中并使该文件可执行,然后才能运行脚本。

注意为了您的安全,我特意从 Perl 命令中删除了就地编辑选项,因此脚本只会打印出对文件内容的修改,但不会进行实际编辑...您需要在验证安全后将该选项添加到 Perl 命令中。

答案2

我使用了 Raffa 的答案,并从 Perl 命令中添加了就地编辑选项,因此脚本实际上会对文件内容进行修改。请注意,此版本很危险,因为它实际上会对文件进行更改。请注意,这还会在进行更改之前创建原始文件的备份。

#!/bin/bash

# This file = /usr/local/bin/stringfindreplace.sh
# Find and replace a string in files recursively starting at the current directory.
# https://askubuntu.com/questions/1507419/how-to-write-a-bash-script-from-two-commands-find-and-replace-a-text-string-in
# Put this file "stringfindreplace.sh" in /usr/local/bin. Then run "sudo chown your-user-name-here: /usr/local/bin/stringfindreplace.sh && chmod +x /usr/local/bin/stringfindreplace.sh".
# If you need to modify root files or files owned by root, then run "sudo stringfindreplace.sh" to activate this script with root privileges.
# If you need to only modify user files, then just run "stringfindreplace.sh" to activate this script with user privileges.

while read -r -p "You are in \"$PWD\". Is this the right directory? [y(es)|n(o)|q(uit): "; do
  case "$REPLY" in
    y) read -r -p "Please, enter the search string: "
       readarray -d '' files < <(grep -rF -l --null "$REPLY")
       if [[ "${#files[@]}" -eq 0 ]]; then
         printf '%s\n' "no matches found ... exiting"
         unset files
         exit
       else
         search="$REPLY"
         printf '%s\n' "${files[@]}" | less
         read -r -p "Matches found ${#files[@]}. Please, enter the replacement string: "
         replacement="$REPLY"
         printf '%s\0' "${files[@]}" |
         xargs -0 -r perl -pi~stringfindreplace.orig -e "s/${search}/${replacement}/g"
         echo "Your strings have been replaced in the earlier listed files. Backups were created with filename~stringfindreplace.orig extension."
       fi
       unset files
       exit
       ;;
   n) while true; do
        read -r -p "Enter the correct directory path: "
        if ! [ -z "$REPLY" ]; then
          cd "$REPLY" && break
          fi
        done
        ;;
   q) exit
      ;;
   *) printf '%s\n' "Invalid input"
      ;;
  esac
done

相关内容