Нужна помощь в создании сценария для переименования текстовых файлов и перемещения их в каталог

Начиная с Ubuntu12.10, в Unity добавлен новый объектив для покупок. Вы можете узнать больше об этом на OMG! Ubuntu! , Этот объектив включает все соответствующие результаты от Amazon.

2
задан 29 February 2012 в 23:00

7 ответов

Откройте терминал и откройте текстовый редактор, используя эту команду (gedit или ваш любимый!)

gedit ~ / .gnome2 / nautilus-scripts / Notes

Это откроет файл в папке Scripts Nautilus (файл браузера) для некоторой магии, которую вы скоро увидите: D Теперь скопируйте следующий упрощенный код в gedit и сохраните. (Вы можете использовать Marcelo Morales, если хотите: P)

#!/bin/bash

# Words prefixed with a hash are comments.

# Save directory. Add in your own username and directory here.
movePath=/home/<username>/notes

# Iterate over files in current folder.
for noteFile in **
do
# Check if is a notes file (even if UPPERCASE or lowercase), and not already edited.
    if [[ ${noteFile,,} == *"notes"* ]] && [[ ${noteFile,,} != *".txt" ]] && [[ ! -d "$noteFile" ]]
    then
        # If so, move and rename the file to your save directory.
        mv "$noteFile" "$movePath/$noteFile.txt"
    fi
done

Предоставить исполняемые разрешения сценария.

gedit ~ / .gnome2 / nautilus-scripts / Notes [ ! d2]

chmod u + x ~ / .gnome2 / nautilus-scripts / Notes

Теперь, чтобы увидеть магию скриптов Nautilus. Щелкните правой кнопкой мыши в папке с файлом «примечания» или двумя внутри, перейдите в «Сценарии», а затем нажмите «Заметки», и вы будете волшебным образом видеть, что все ваши файлы заметок превращаются в «notes * .txt»

2
ответ дан 25 May 2018 в 22:19
  • 1
    См. mywiki.wooledge.org/BashPitfalls . В частности, ловушки 1 и 2. – geirha 2 April 2011 в 02:57
  • 2
    Не беспокойтесь, полностью случайно просмотрел пробелы: S Спасибо за хорошее чтение, действительно заметил мои вредные привычки haha ​​Добавил изменения в свой ответ, чтобы компенсировать; хотя по какой-то причине, если файл вызывается просто «нотами», он не изменит его. У меня такое чувство, что это может быть связано с подстановочными знаками, хочу пролить свет на эту гейрху? :П – Alex Stevens 4 April 2011 в 19:07
  • 3
    Если вы запустите сценарий в своем домашнем каталоге, а целевой каталог - ~/notes, то он, очевидно, не сработает на notes, поскольку перемещение каталога внутри себя невозможно. Вы можете использовать [[ $noteFile -ef $movePath ]] для проверки, являются ли два файла одинаковыми (см. [F4]). Еще несколько комментариев: 1) *"notes"*[^.txt] не соответствует тому, что, по вашему мнению, соответствует. 2) В bash4 вы можете вводить строчные значения с расширением параметра "${noteFile,,}". mywiki.wooledge.org/BashSheet#Parameter_Operations – geirha 5 April 2011 в 02:52
  • 4
    Человек, ты спасатель. Кроме того, эта wiki является BASH gold: P Обновил код, не пробовал слишком много сумасшедших вещей. Бросьте проверку каталога, чтобы мы не получали глупых ошибок. – Alex Stevens 5 April 2011 в 05:05

Это может заставить вас начать:

#!/bin/bash

find . -name 'note*' -not -name '*txt' -exec mv -bf '{}' '{}'.txt \;
find . -name 'note*.txt' -exec mv -bf '{}' /home/username/notes/ \;

-bf заставляет mv не задавать вопросы и выполнять резервное копирование при перезаписи.

4
ответ дан 25 May 2018 в 22:19
  • 1
    Проблемы! Сценарий не ведет себя так, как ожидалось ... Когда я запускаю скрипт, он рекурсивно вытягивает все в моем домашнем каталоге с текстом "home " в нем и не заканчивается в .txt " – Peter.O 2 April 2011 в 20:28

Это будет безопасно обрабатывать имена файлов.

#!/bin/bash
shopt -s extglob  # see http://mywiki.wooledge.org/glob

for file in note!(*.txt); do
    mv -i "$file" "$HOME/notes/$file.txt"
done
mv -i note*.txt "$HOME/notes/"

Если вы хотите нечувствительность к регистру, также включите опцию оболочки nocaseglob.

shopt -s extglob nocaseglob [!d2 ]

EDIT: Другой подход

#!/bin/bash
for file in note*; do
    # Make sure it's a regular file and not the destination directory
    [[ -f $file && ! $file -ef $HOME/notes ]] || continue
    mv -i "$file" "$HOME/notes/${file%.[Tt][Xx][Tt]}.txt"
done
2
ответ дан 25 May 2018 в 22:19
  • 1
    @geirha ... Ваша общая идея находится на пути (мне нравится глобус), но у нее есть некоторые проблемы ... 1) она не обрабатывает имена файлов со встроенными пространствами ... 2) вы перемещаете файлы дважды !. .. 3) он пытается переместить каталоги и ссылки с именем «note *». – Peter.O 2 April 2011 в 20:17
  • 2
    @ fred.bear 1) Он обрабатывает любое имя файла, почему вы думаете, что нет? 2) Он не перемещает файлы дважды ... если текущий каталог не является "$HOME/notes/". 3) Да, да. Если это нужно или нет, вопрос не говорит ... – geirha 2 April 2011 в 20:58
  • 3
    @geirha: для 1) Не удалось обработать файлы со встроенными пространствами: «примечание 1» "примечание 2" .... и для 2) первый mv перемещает файл из текущего каталога, а второй mv по-прежнему является текущим в теперь «пустой», original dir ... И в любом случае mv позволяет вам переименовывать и перемещать одновременно; зачем дважды обращаться к каталогам? ... 3) вопрос действительно ... (the) целью было бы переименовать все текстовые файлы в ... – Peter.O 2 April 2011 в 21:32
  • 4
    Вот сообщение об ошибке для (1): mv: cannot move "notes" to a subdirectory of itself, "/home/fred/notes/notes.txt" Этот конкретный файл на самом деле назван note 1. – Peter.O 2 April 2011 в 21:35
  • 5
    @ fred.bear, что сообщение об ошибке безопасно, а не файл с именем note 1 ... – geirha 2 April 2011 в 21:56

Обновленная версия: согласно полезным предложениям geirha.

Я избавился от массива, что было совершенно ненужным, и внесло изменения в то, как и какие глобальные настройки установлены / не установлены. Оригинальная версия по-прежнему включена; (для сравнения)

################################################
cd ~/ # create sample files with embedded spaces 
touch note\ {1..3}
################################################
#  
tdir="$HOME/notes"; # make target dir
[[ ! -d "$tdir" ]] && mkdir -p "$tdir"
#  
shopt -q nullglob; Xnullglob=$? # state of nullglob  
shopt -s nullglob                 # enable nullglob
shopt -s extglob                  # enable  extglob
#  
for f in note!(*.txt) ; do
  if [[ -f $f ]] ; then
     mv -i "$f" "$tdir/$f.txt"
  fi 
done
#  
((Xnullglob==1)) &&  shopt -u nullglob # Reset nullglob 
#

Оригинальная версия (с дополнительным треском):

cd ~/ 
# create some sample files with embedded spaces
touch note\ {1..3}
#  
tdir="$HOME/notes";   # make target dir if not present
[[ ! -d "$tdir" ]] && mkdir -p "$tdir"
#  
state=($(shopt extglob)) # Save extended globbing state  
[[ ${state[1]} == off ]] &&  shopt -s extglob
#  
farray=( note!(*.txt) )  # Build an array of filenames
fcount=${#farray[@]}     # Get size of the array
#  
for ((findex=0; findex<fcount; findex++));do
  if [[ -f "${farray[findex]}" ]] ; then
     echo -e $findex "${farray[findex]}"    
     mv -i "${farray[findex]}" \
     "$tdir/${farray[findex]}.txt"
  fi 
done
#  
[[ ${state[1]} == off ]] &&  shopt -u extglob # Reset extglob 
#  
# `mv -i` will interactively check with you before overwiting and existing file.
#  You can use `mv -bf` to backup an existing file before overwriting it.
2
ответ дан 25 May 2018 в 22:19
  • 1
    Несколько комментариев по этому поводу: 1) Я не вижу смысла в настройке и отключении extglob. Когда скрипт запустится, он отключится. И поскольку это не повлияет на регулярные глобусы, нет смысла отключать его вообще. 2) Для итерации массива я просто использую for file in "${farray[@]}";. Короче и проще. 3) Мы оба забыли - установить значение nullglob для учета отсутствия файлов, соответствующих шаблону. 4) Наконец, ваш скрипт не перемещает файлы, которые заканчиваются на .txt. – geirha 2 April 2011 в 22:04
  • 2
    :) .. Я думал, вы найдете что-то. Хорошо. Об отключении extglob. Я подумал об этом, но, поскольку скрипт bash для меня совершенно новый (6 месяцев), я просто хотел попробовать сделать это. В более длинном скрипте это может пригодиться (когда-нибудь), поэтому это было хорошее место для практики:) ... Повторяя массив. Да, я полагаю, это сработает. Я все еще пытаюсь работать, когда и где bash- слова теряют свою целостность и разделение слов .. Я не хочу, чтобы это сэкономило много индивидуальных доступов элементов массива ... (спасибо) .. re " nullglob " Я не забыл :), но я был на перегрузке, поэтому я проигнорировал это. – Peter.O 2 April 2011 в 22:44
  • 3
    ... продолжение: повторить расширение .txt, он действительно говорит "именованный, например. & Quot; примечание * & Quot; (без расширения) " ... но теперь я понимаю, почему ваш обновленный скрипт действительно обслуживал расширение, которое должно быть включено в расширение файла shell. btw .. Ваш новый обновленный метод выглядит великолепно .. приятно и просто и прямо вперед ... и .txt легко подстраивается в любом случае .... Это очень поздно здесь .. нужно идти ... bye :) – Peter.O 2 April 2011 в 22:52
  • 4
    bear Ну, не имеет смысла отключать extglob. Однако nullglob имеет смысл отключить, как только он больше не понадобится. nullglob будет иметь "неожиданное" если у вас нет полного контроля над тем, какие расширения происходят в этот момент. Обратите внимание, что shopt nullglob вернет false, если он не установлен, и true, если он установлен. Намного лучше просто проверить возвращаемое значение, а не сравнение строк. См. mywiki.wooledge.org/Arguments для подробного объяснения разбиения слов. – geirha 3 April 2011 в 00:03

for noteFile in note*[^.txt]; do mv $noteFile /home/username/notes/$noteFile.txt; done

Мне нравится этот ответ лучше :) Единственным недостатком является то, что он перемещает только файлы, которые он переименовал

-1
ответ дан 25 May 2018 в 22:19
  • 1
    Будет ли это работать с именами файлов, которые имеют пробелы ?. На первый взгляд кажется, что нет. – Marcelo Morales 1 April 2011 в 03:59
  • 2
    note*[^.txt] будет соответствовать всем файлам, начиная с note и не заканчиваться на ., t или x. Также см. Mywiki.wooledge.org/BashPitfalls. – geirha 2 April 2011 в 03:01
  • 3
    ты прав! Баш раздражает. Я пытался использовать другие методы, например for my_file in $((ls note*.txt; ls note*) | sort | uniq -u); do mv $my_file /where/ever; done, но это неправильно обрабатывает пробелы. :( Есть переменная IFS, с которой вы можете столкнуться, но это выходит за рамки моих навыков bash. – user1974 2 April 2011 в 21:41
  • 4
    @ user1974 ls выводит представление файлов, а не имена файлов, они просто бывают одинаковыми для простых случаев (например, если в именах файлов нет нечетных символов). IFS позволит вам обрабатывать еще несколько случаев, но это отнюдь не решение. ls никогда не должен использоваться в сценарии. Смотрите fred.bear и мои ответы на предмет глобуса, который сделает то, что вы хотите. Кроме того, не забывайте кавычки. – geirha 3 April 2011 в 00:10
  • 5
    @ User1974. Еще немного о том, как использовать «цитированные имена файлов». В примерах как моего, так и гейрхи вы увидите, что имя файла используется без котировок (но не везде). Это связано с тем, что конструкция [[...]] не выполняет никакого расщепления слов, поэтому с или без котировок в порядке. Обратите внимание, что более старая версия с одним кронштейном не защищает " переменные таким образом, поэтому вам понадобятся кавычки, когда могут быть задействованы пробелы ... Более двойные скобки: ((...)) для целых условий ((x == 1)) и присваивание / вычисление ((x + = 1)); вам не нужны $ или пробелы с целыми числами. – Peter.O 3 April 2011 в 15:31

Это безопасно будет обрабатывать имена файлов.

#!/bin/bash
shopt -s extglob  # see http://mywiki.wooledge.org/glob

for file in note!(*.txt); do
    mv -i "$file" "$HOME/notes/$file.txt"
done
mv -i note*.txt "$HOME/notes/"

Если вы хотите нечувствительность к регистру, также включите опцию оболочки nocaseglob.

shopt -s extglob nocaseglob

EDIT: Другой подход

#!/bin/bash
for file in note*; do
    # Make sure it's a regular file and not the destination directory
    [[ -f $file && ! $file -ef $HOME/notes ]] || continue
    mv -i "$file" "$HOME/notes/${file%.[Tt][Xx][Tt]}.txt"
done
2
ответ дан 4 August 2018 в 19:49

Это безопасно будет обрабатывать имена файлов.

#!/bin/bash
shopt -s extglob  # see http://mywiki.wooledge.org/glob

for file in note!(*.txt); do
    mv -i "$file" "$HOME/notes/$file.txt"
done
mv -i note*.txt "$HOME/notes/"

Если вы хотите нечувствительность к регистру, также включите опцию оболочки nocaseglob.

shopt -s extglob nocaseglob

EDIT: Другой подход

#!/bin/bash
for file in note*; do
    # Make sure it's a regular file and not the destination directory
    [[ -f $file && ! $file -ef $HOME/notes ]] || continue
    mv -i "$file" "$HOME/notes/${file%.[Tt][Xx][Tt]}.txt"
done
2
ответ дан 10 August 2018 в 10:03

Другие вопросы по тегам:

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