Переименование нескольких файлов в нескольких подкаталогах с помощью цикла for

На основе файла примера ответ Steeldriver (использование таблицы поиска/ассоциативного массива вawk)наверное лучшее решение. Хотя это вообще не рекомендуется, вы можете сделать то же самое только в bash:

declare -A id
while IFS="," read x idnum xx name
do
        id[$name]=$idnum
done < file1
while read name
do
        printf '%s %s\n' "${id[$name]}" "$name"
done < file2

Логика та же:

  1. Первый проход, который создает массив, индексируется значениями имен, содержащими значения идентификаторов.
  2. Второй проход, который сопоставляет имена с идентификаторами и выводит их рядом.

Мой ответ работает так, как хотелось (, т.е. как указано )для образца данных в вопросе. (Поскольку он использует массив — в частности, ассоциативный массив — для этого требуется bash (или ksh, zsh или yash ); массивы не указаны в спецификации POSIX для оболочки, и доступны не во всех оболочках, используемых в Unix/Linux. )Из-за того, как работает команда bash read, мой ответ также обрабатывает имена из нескольких -слов (, то есть имена с пробелами в них )как можно интуитивно ожидать:

        file1                             file2                    output

ID: 42, Name: fat cat                   fat cat                  42 fat cat
ID: 95, Name: Superman                  under dog                83 under dog
ID: 83, Name: under dog                 spider man      ⟹       17 spider man
ID:  9, Name: cat woman                 spider pig               60 spider pig
ID: 17, Name: spider man                Superman                 95 Superman
ID: 60, Name: spider pig                cat woman                9 cat woman

Обратите внимание, что оба ответа чувствительны -к регистру; например, foo1.bar.comне будет соответствовать Foo1.bar.com.

0
28.04.2021, 16:12
1 ответ

Вы можете использовать подобный код.

#!/bin/bash

# Loop across the list of directories
for dir in Subdirectory1 Subdirectory2
do
    # Only consider directories
    [ -d "$dir" ] || continue

    # Loop across any files in each directory
    for src in "$dir"/*.txt
    do
        dst="$dir/$dir.txt"
        
        # Only rename a file if it won't overwrite another one
        if [ -f "$dst" ]
        then
            # Refuse to overwrite
            echo "Target file already exists: $dst" >&2
        else
            # If the file already has the right name just skip
            [ -f "$src" ] && [ "$src" != "$dst" ] && mv -f -- "$src" "$dst"
        fi
    done
done

Подготовьте скрипт (допустим, он называетсяrenamethemchmod a+x renamethem. А затем запустите его как ./renamethem.

Вы увидите, что список каталогов жестко -закодирован в цикле for. Есть несколько других способов сделать это немного более элегантно.Вы можете указать список в командной строке (./renamethem Subdirectory1 Subdirectory2), и в этом случае измените одну строку на for dir in "$@", чтобы выбрать параметры из этой командной строки. Или вы можете использовать массив (список ). Или вы можете использовать *для сопоставления всех каталогов в текущем каталоге.

1
28.04.2021, 22:50

Теги

Похожие вопросы