Переместить все файлы, НЕ заканчивающиеся на .txt [дубликат]

Это довольно просто с awk , возможно, выполнимо с sed .

С awk у вас будет состояние, которое устанавливается / сбрасывается в каждой строке typedef и заканчивается в каждой строке правой фигурной скобкой. Подходящий сценарий awk будет выглядеть как

BEGIN {
    state = 0;
    typedef="";
    fields="";
}
/typedef[ ]+struct/{
    state = 1;
    typedef=$3;
    next;
}
/}.*;/ {
    if (state != 0) {
        sub("^.*}[  ]*","",$0);
        sub(";","",$0);
        sub(",$","",fields);
        printf "%s %s: %s\n", typedef, $0, fields;
        state = 0;
        fields = "";
        typedef = "";
    }
    next;
}
(state == 1){ 
    gsub("[     ]+"," ", $0);
    gsub(";",",",$0);
    fields = fields $0;
    next;
}

, где квадратные скобки [ и ] заключают пробел и табуляцию (чтобы сделать его переносимым). Сценарий состоит из четырех частей:

  1. действие BEGIN инициализирует переменные (не обязательно, но некоторые awks делают несколько разные вещи с неинициализированными переменными)
  2. шаблон, соответствующий строке с typedef , за которым следуют пробелы и слово struct . Это ожидает как минимум 3 поля в строке, используя третье в качестве имени typedef.
  3. шаблон, соответствующий закрывающей фигурной скобке. На случай, если в вашем файле есть что-то еще, действие проверяет, установлено ли состояние . $ 0 - текущая строка. Первая замена удаляет все, что находится перед интересующим нас словом, а вторая удаляет точку с запятой, следующую за ним. Третья замена заменяет запятую после переменной fields , полученной в результате 4-го действия (ниже), на пустую строку.
  4. шаблон, соответствующий всем другим строкам , когда установлено состояние . Как и в предыдущем действии, здесь используется подстановка для удаления ненужных частей, сначала путем сокращения нескольких пробелов до одного пробела, а затем замены конечной точки с запятой на запятую.

Вызовите этот файл foo.awk и ваши входные данные foo.in , чтобы использовать awk следующим образом:

awk -f foo.awk 

Если вы хотите сопоставить строки, подобные этой:

struct foo {

, а не

typedef struct foo {

, тогда образец можно было бы записать

/^([  ]*typedef)?[  ]+struct[  ]+/{

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

Дополнительная литература:

11
02.01.2019, 13:50
4 ответа

Вариант простой петли оболочки (вbash):

shopt -s extglob dotglob nullglob

for pathname in ~username/data/!(*.txt); do
    ! test -d "$pathname" && mv "$pathname" ~username/data/other_files
done

Параметры оболочки, установленные в первой строке, заставят оболочку bashвключить расширенные шаблоны подстановок(!(*.txt)для соответствия всем именам, не заканчивающимся на .txt), это позволяет шаблонам подстановок соответствовать скрытым именам, и это делает шаблон расширяться до нуля, если ничего не совпадает.

Тело цикла пропустит все, что является каталогом (или символической ссылкой на каталог ), и переместит все остальное в заданный каталог.

Эквивалентная вещь с findи GNUmv(будет перемещать символические ссылки на каталоги, если они есть, и вызывать mvдля максимально возможного количества файлов одновременно, но это единственные различия ):

. ]
find ~username/data -maxdepth 1 ! -type d ! -name '*.txt' \
    -exec mv -t ~username/data/other_files {} +

Связанные:

13
27.01.2020, 19:57

Этот код должен переместить все файлы, не заканчивающиеся на «.txt», в вашу целевую папку, однако, если у вас есть файлы с одинаковыми именами по разным путям, это вызовет ошибку.

find /home/username/data ! -name "*.txt" -type f -maxdepth 1 -exec mv {} /home/username/data/other_files/ \;
2
27.01.2020, 19:57
find /home/username/data -maxdepth 1 -type f ! -name '*.txt' -exec mv {} /home/username/data/other_files/ \;
  • Ограничения максимальной глубины для главных директоров
  • тип гарантирует, что будут найдены только файлы, а не каталоги
7
27.01.2020, 19:57

Следующая строка находит все файлы и скрытые файлы в текущем каталоге, которые не являются *.txtи не являются путем, и перемещает их в новый путь:

ls -1p | grep -v "^.*\.txt$" | grep -v ".*/$" | xargs mv -vt newpath

Следующее то же самое, но также перемещает скрытые файлы:

ls -1ap | grep -v "^.*\.txt$" | grep -v ".*/$" | xargs mv -vt newpath

Обе командные строки не сканируют каталоги рекурсивно и не перемещают каталоги

Если у вас есть имена файлов, содержащие пробелы, вы можете использовать:

ls -1ap | grep -v "^.*\.txt$" | grep -v ".*/$" | xargs -d'\n' printf "\"%s\"\n" | xargs mv -vt newpath

1
27.01.2020, 19:57

Теги

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