Supposons que j'ai un répertoire contenant environ 100 fichiers .rtf
que je modifie avec LibreOffice Writer.
Je souhaite que tous les fichiers de ce répertoire aient exactement les mêmes directives de style de texte enrichi, par exemple:
* font-family: Ubuntu # All text in all files is now Ubuntu;
* font-size: 12px # All text in all files is now 12px big;
h1: 28px # All h1's are now 28px big;
if font-size: 18px {make it 22px} # All text with font-size 18px is now 22px;
Et ainsi de suite ... Donc, fondamentalement, je veux changer tous les fichiers en même temps. Un tel "style en vrac" est-il possible?
Peut-être que c'est possible avec le CLI en quelque sorte?
Lorsque tout ce que vous avez est un outil de ligne de commande, tout ressemble à un problème de ligne de commande. J'ai décidé d'écrire cette réponse à l'aide de macros LibreOffice:
.rtf
(Rich Text Format).Créez deux fichiers ou plus contenant:
Créez le script ~/Downloads/copy-rtf.sh
contenant:
cp ~/Documents/*.rtf ~/Downloads
Marquer comme exécutable en utilisant
chmod a+x ~/Downloads/copy-rtf.sh
*.rtf
seront exécutées dans le répertoire ~/Downloads
.cd ~/Downloads
et exécutez ./copy-rtf.sh
Le répertoire Téléchargements est utilisé pour les raisons suivantes:
~/Downloads
/tmp/
qui peut ne pas persister après les redémarrages.En utilisant ceci réponse Stack Exchange , appelez Libreoffice Writer à partir de la ligne de commande et transmettez-lui un nom de macro global à exécuter:
soffice -headless -invisible "vnd.Sun.star.script:Standard.Module1.MySubroutine? language=Basic&location=application"
La réponse ci-dessus peut ne pas fonctionner de la sorte ne autre méthode peut être essayée:
soffice "macro:///Standard.SaveCSV.Main" $1
Pour exécuter des macros, vous devez disposer de Java Environnement d'exécution (JRE). La page Web du développeur contient instructions pour le téléchargement et l’installation manuelle.
Cependant, ce Q & A de l'UA: https://askubuntu.com/a/728153/30752 suggère qu'il est aussi simple que:
Sudo apt-add-repository ppa:webupd8team/Java
Sudo apt-get update
Sudo apt-get install Oracle-Java8-installer Oracle-Java8-set-default
J'ai essayé la méthode de questions et réponses de l'UA et après la première étape de l'ajout du PPA, un écran de démarrage apparaît avec des informations supplémentaires. Le plus utile est un lien vers configuration de JRE 8 sur les systèmes Debian .
La troisième étape de l’installation de JRE 8 nécessite l’utilisation de Tab et Enter accepter le contrat de licence. Votre machine s'interrompra quelques minutes au cours de la partie la plus lourde de la procédure d'installation.
Ouvrez maintenant LibreOffice et sélectionnez Outils -> Options -> LibreOffice -> Avancé et configurez cet écran:
Cliquez sur les options pour:
La macro lira l’ensemble du document et:
La macro enregistrera le document et quittera Libreoffice Writer.
Faites une sauvegarde de fichier et cette boîte de dialogue apparaît:
Désactivez ce message comme indiqué à l'écran. La macro peut ne pas fonctionner correctement si cette option est activée.
J'ai passé quelques jours à essayer d'enregistrer une macro en utilisant "Outils" -> "Macros" -> "Enregistrer une macro" -> "Basique". Au début, cela semblait prometteur, mais la macro enregistrée avait un comportement incohérent et devait être abandonnée pour une macro de base écrite à la main. Une aide trouvée dans Stack Overflow pour un expert là-bas pour m'aider avec la base codage de base . Voici le résultat:
Sub ChangeAllFonts
rem - Change all font names to Ubuntu.
rem - If heading 1 set font size to 28
rem - else if font size is 18 set to 22
rem - else set font size to 12
rem - The macro will save document and exit LibreOffice Writer.
Dim oDoc As Object
Dim oParEnum As Object, oPar As Object, oSecEnum As Object, oSec As Object
Dim oFamilies As Object, oParaStyles As Object, oStyle As Object
oDoc = ThisComponent
oParEnum = oDoc.Text.createEnumeration()
Do While oParEnum.hasMoreElements()
oPar = oParEnum.nextElement()
If oPar.supportsService("com.Sun.star.text.Paragraph") Then
oSecEnum = oPar.createEnumeration()
Do While oSecEnum.hasMoreElements()
oSec = oSecEnum.nextElement()
If oSec.TextPortionType = "Text" Then
If oSec.ParaStyleName = "Heading 1" Then
rem ignore for now
ElseIf oSec.CharHeight = 18 Then
oSec.CharHeight = 22.0
Else
oSec.CharHeight = 12.0
End If
End If
Loop
End If
Loop
oFamilies = oDoc.getStyleFamilies()
oParaStyles = oFamilies.getByName("ParagraphStyles")
oStyle = oParaStyles.getByName("Heading 1")
oStyle.setPropertyValue("CharHeight", 28.0)
FileSave
StarDesktop.terminate()
End Sub
rem Above subroutine is missing call to UbuntuFontName ()
rem also it is calling oStyle.setPropertyValue("CharHeight", 28.0)
rem which may cause problems. Will test. Also StarDesktop.terminate ()
rem is known to cause problems and will likely be reworked with a
rem a dialog box telling operator the program is finished and maybe
rem to press <Alt>+<F4>.
rem ========= Original code below for possible recycling ===========
Sub AllFonts
rem - change all font names to Ubuntu.
rem - If heading 1 set font size to 28
rem - else if font size is 18 set to 22
rem - else set font size to 12
rem The macro will save document and exit Libreoffice Writer.
Dim CharHeight As Long, oSel as Object, oTC as Object
Dim CharStyleName As String
Dim oParEnum as Object, oPar as Object, oSecEnum as Object, oSec as Object
Dim oVC as Object, oText As Object
Dim oParSection 'Current Section
oText = ThisComponent.Text
oSel = ThisComponent.CurrentSelection.getByIndex(0) 'get the current selection
oTC = oText.createTextCursorByRange(oSel) ' and span it with a cursor
rem Scan the cursor range for chunks of given text size.
rem (Doesn't work - affects the whole document)
oParEnum = oTC.Text.createEnumeration()
Do While oParEnum.hasMoreElements()
oPar = oParEnum.nextElement()
If oPar.supportsService("com.Sun.star.text.Paragraph") Then
oSecEnum = oPar.createEnumeration()
oParSection = oSecEnum.nextElement()
Do While oSecEnum.hasMoreElements()
oSec = oSecEnum.nextElement()
If oSec.TextPortionType = "Text" Then
CharStyleName = oParSection.CharStyleName
CharHeight = oSec.CharHeight
if CharStyleName = "Heading 1" Then
oSec.CharHeight = 28
elseif CharHeight = 18 Then
oSec.CharHeight = 22
else
oSec.CharHeight = 12
End If
End If
Loop
End If
Loop
FileSave
stardesktop.terminate()
End Sub
Sub UbuntuFontName
rem ----------------------------------------------------------------------
rem define variables
dim document as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.Sun.star.frame.DispatchHelper")
rem ----------- Select all text ------------------------------------------
dispatcher.executeDispatch(document, ".uno:SelectAll", "", 0, Array())
rem ----------- Change all fonts to Ubuntu -------------------------------
dim args5(4) as new com.Sun.star.beans.PropertyValue
args5(0).Name = "CharFontName.StyleName"
args5(0).Value = ""
args5(1).Name = "CharFontName.Pitch"
args5(1).Value = 2
args5(2).Name = "CharFontName.CharSet"
args5(2).Value = -1
args5(3).Name = "CharFontName.Family"
args5(3).Value = 0
args5(4).Name = "CharFontName.FamilyName"
args5(4).Value = "Ubuntu"
dispatcher.executeDispatch(document, ".uno:CharFontName", "", 0, args5())
end sub
sub FileSave
rem ----------------------------------------------------------------------
rem define variables
dim document as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.Sun.star.frame.DispatchHelper")
rem ----------------------------------------------------------------------
dispatcher.executeDispatch(document, ".uno:Save", "", 0, Array())
end sub
Voici une approche ponctuelle utilisant Libre Office. Ce n'est pas un lot, mais cela peut inspirer d'autres réponses.
Ouvrez un fichier rtf contenant la police Ubuntu, H1 à 28 points, du texte à 12 points et d’autres à 18 points.
Voici un exemple:
Les étapes suivantes appliqueront la modification demandée dans votre question "si la taille de la police: 18px {la rendre 22px} # # tout le texte avec la taille de la police 18px est maintenant 22px;"
Cliquez sur Édition → Rechercher et remplacer dans le menu ou appuyez sur CtrlH Autres options Cliquez sur la boîte de recherche puis sur le bouton d'attributs Taille de la police, puis sur le bouton Format, puis sélectionnez 18 pt dans la zone de défilement extrême droite. Cliquez sur Remplacer par une case, puis le bouton Format et sélectionnez 22 pt dans la zone de défilement extrême droite.
Cliquez sur Remplacer tout
la ligne applicable qui a changé était:
\ par\pard\plain\s0\ql\widctlpar\hyphpar0\ltrpar\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\fg24\langl33\ql\widctlpar\hyphpar0\ltrpar {\ rtlch\ltrch\loch\fs36\loch\f6
le fs36 changé en fs44
le seul autre champ qui a changé est le champ revtime que vous ne souhaitez peut-être pas mettre à jour:
{\ revtim\yr2018\mo3\dy31\hr22\min19}
Savoir ce qui a changé nous fournit un modèle pour développer une approche par lots. Il est probablement possible d'enregistrer une macro qui le fait lors de l'ouverture d'un document ou de développer un script qui apporte les modifications souhaitées.
Il existe de très bons indices sur la manière dont on pourrait s'y prendre dans la spécification RTF.
Voici mon analyse de la question.
Accomplir ceci en utilisant la CLI comme vous le supposez semble être l'approche la plus simple car je n'ai vu aucune application à interface graphique pouvant gérer ce type de conversion par lots. Il semble que vous puissiez simplement modifier l'en-tête:
L'en-tête a la syntaxe suivante:
<header>
\rtf <charset> \deff? <fonttbl> <filetbl>? <colortbl>? <stylesheet>? <listtables>? <revtbl>?
Each of the various header tables should appear, if they exist, in the above order. Document properties can occur before and between the header tables. A property must be defined before being referenced. Specifically:
* The style sheet must occur before any style usage.
* The font table must precede any reference to a font.
* The \deff keyword must precede any text without an explicit reference to a font, because it specifies the font to use in such cases.
Personnellement, à la lecture de ces informations, je me rends compte que tout ce que vous essayez de faire semble être pris en charge dans l’en-tête, de la sélection de police à style.
Il existe des outils pour vous aider dans ce processus que je décrirai ci-dessous comme suit: Je n'ai pas d'exemple de style de document ni de style de document que vous souhaitez et une réponse plus générique sera probablement plus utile à la communauté qu’une réponse à votre situation exacte.
grep
sera utile pour analyser les fichiers existants à convertir et un exemple du style cible pour <fonttbl>
existant et<stylesheet>
sélections. Une fois que vous avez déterminé ce que vous avez réellement, vous devriez être capable d’écrire un script simple utilisant sed
pour remplacer le contenu de l’en-tête existant par le contenu de l’en-tête souhaité. Il existe de nombreux exemples illustrant comment parcourir des fichiers dans un script bash ( exemple ) et comment utiliser sed ( exemple ) disponible gratuitement si vous n'êtes pas familiarisé avec ces concepts.
Il existe également des options d'une ligne pour remplacer une chaîne dans un fichier. Certains peuvent fonctionner mieux que d'autres, selon votre cas d'utilisation. En fonction du contenu de vos fichiers, il peut être judicieux de remplacer simplement chaque instance de fs36
par fs44
. Le shell que vous utilisez peut également avoir une incidence sur la meilleure façon d'écrire vos expressions. En fonction de la complexité et du contenu de vos documents, il peut être préférable d'utiliser sed
name__, Perl
ou grep
ou même une combinaison de ceux-ci. Comme cela est devenu une question de programmation, il est préférable de vous renvoyer https://stackoverflow.com/questions/15402770/how-to-grep-and-replace où vous trouverez facilement un 1/2 douzaines d’approches différentes, dont l’une est parfaitement adaptée à vos besoins.
Par exemple, si vous souhaitez appliquer ces modifications à l’ensemble du système,
find /path/to/files -type f -exec sed -i 's/oldstring/newstring/g' {} \;
tel que fourni par rezizter Est probablement le meilleur.
Si vous souhaitez contenir vos modifications dans un seul répertoire,
grep -rl matchstring somedir/ | xargs sed -i 's/fs36/fs44/g'
as fourni par billtian est un excellent choix.
Pour plus de sécurité, vous devez prétraiter les fichiers pour vous assurer que les modifications que vous apporterez n'auront pas de conséquences inattendues. Par exemple:
<!-- language: lang-bash -->
#!/bin/bash
for f in *.rtf
do
echo $f
grep fs36
done
Ce qui précède affichera les lignes contenant la chaîne de recherche fs36 pour chaque fichier .rtf du répertoire.
Modifier:
La spécification la plus récente peut être obtenue ici. Je ne vois aucun changement susceptible d'influencer cette approche.