├── README.md └── alias_creator.py /README.md: -------------------------------------------------------------------------------- 1 | # Obsidian Alias File Generator 2 | 3 | A python script that compiles a yaml file of noted aliases for all notes within an obsidian vault. Makes easier forward linking possible. 4 | 5 | Useful in creating shorthand names for notes due to acronym usage or to link in intext citations. 6 | 7 | ### Function 8 | This script performs the following function: 9 | - Searches an obsidian vault for all markdown files 10 | - Inspects each file for an alias keyword tag 11 | - If tag found, extracts the subsequent alias names for that file 12 | - Compiles all filenames and related tags into a YAML file 13 | 14 | ### NOTE 15 | This script is designed to do some of the heavy lifting of creating a YAML file to feed into [**Ben Perkins'** great work to create forward links in obsidian notes](https://github.com/perkinsben/obs_tools/tree/master/forward_linker) 16 | 17 | The intent of this script/method is to manage the alias names directly within obsidian notes, rather than in a secondary document (the .yaml file) which is a degree of separation away from the note in question. 18 | 19 | ------ 20 | ## Requirements 21 | 22 | ### Python 23 | * Python 3 + pip 24 | * [PyYAML](https://pypi.org/project/PyYAML/) 25 | 26 | ``` 27 | pip install pyyaml 28 | ``` 29 | 30 | ### Obsidian 31 | Within your markdown note file(s) an alias 'tag' must be added in the text to identify that the line contains aliases for the filename. This tag can be any unique string, but should be placed at the beginning of the line. 32 | 33 | Alias tags can be any combination of characters (string), if you plan on using the tag later in the document and dont want it flagged, set the ```line_limit``` value to a small enough number before you intend to use the tag (i.e. top 10 lines). Best to avoid this and only use a unique tag. 34 | 35 | I tend to use ```::::``` as it is subtle and unobtrusive and place my aliases directly under the note title. But just as easily could be ```See Also:``` or ```=)``` you are only limited by your imagination 36 | 37 | ------ 38 | 39 | ## Running the code 40 | 41 | ### Inputs 42 | The code requires the following inputs: 43 | * Input 0: Path to the python script 44 | * Input 1: Path to vault 45 | * Input 2: Alias search key as a string 46 | * Input 3: Filename for the saved YAML file 47 | * Just the filename (string) without an extension 48 | * e.g. ```aliases``` will create ```aliases.yml``` 49 | * Input 4: Number of lines to limit search from top 50 | * For searching the entire file input ```0``` or ```""``` 51 | * e.g. ```10``` will search only the first ```10 lines``` 52 | * Line limit is used to avoid searching through large notes when you know the alias tag is only always in the first few lines of the file. 53 | 54 | ### Command line 55 | #### If using the guided CLI prompts: 56 | Run the following command in a terminal window. Python will prompt for additional inputs 57 | ``` 58 | python alias_creator.py 59 | ``` 60 | 61 | ### If using CLI directly: 62 | Alternatively you can enter the inputs directly as arguments to speed up the process 63 | ``` 64 | python alias_creator.py {obsidian vault root} {alias key} {yaml filename} {line limit} 65 | ``` 66 | The following would create an ```aliases.yml``` file for my ```Example_Vault``` by searching the first ```10``` lines of all files for the ```::::``` alias tag. 67 | ``` 68 | python alias_creator.py "C:/Obsidian/Example_Vault" "::::" "aliases" "10" 69 | ``` 70 | 71 | 72 | ### For Windows users: 73 | For making it even easier you can create a .BAT file (.txt file with extension change to .bat) and add the direct CLI commands from above. This makes it easier to run as a shortcut, and keep the inputs on hand if you regularly update your alias file. 74 | 75 | ```cmd 76 | @echo off 77 | python alias_creator.py {obsidian vault root} {alias key} {yaml filename} {line limit} 78 | pause 79 | ``` 80 | The following would create an ```aliases.yml``` file for my ```Example_Vault``` by searching the first ```10``` lines of all files for the ```::::``` alias tag. 81 | ``` cmd 82 | @echo off 83 | python ^ 84 | alias_creator.py ^ 85 | "C:/Obsidian/Example_Vault" ^ 86 | "::::" ^ 87 | "aliases" ^ 88 | "10" 89 | pause 90 | ``` 91 | ------- 92 | ## Example usage 93 | 94 | While working on your note called ```Working from home.md``` you would add the alias tag ```::::``` which identifies alternative aliases for the file, and add additional aliases you wish to link this note to. 95 | ```md 96 | # Working from home 97 | :::: Remote working, Remote worker, WFH 98 | 99 | A side effect of the pandemic is that ... 100 | ``` 101 | Executing the script will generate the following entry into your yml alias file: 102 | 103 | ```yaml 104 | Working from home: 105 | - Remote working 106 | - Remote worker 107 | - WFH 108 | ``` 109 | 110 | The script will also include some additional header information within your alias file for tracking when it was last run and under what inputs. This additional header does not negatively impact forward linking code. 111 | 112 | An example of the full output would be: 113 | 114 | ```yaml 115 | # ------------------------------ 116 | # ALIAS FILE FOR OBSIDIAN VAULT 117 | # Vault: Example_Vault 118 | # Created: 19-08-2020, 22:32:05 119 | # ------------------------------ 120 | # Alias Key: '::::' 121 | # Line Limit: 10 lines 122 | # ------------------------------ 123 | 124 | Working from home: 125 | - Remote working 126 | - Remote worker 127 | - WFH 128 | ``` 129 | 130 | --------- 131 | 132 | 133 | ## Acknowledgments 134 | * Shoutout to [Ben Perkins](https://github.com/perkinsben/obs_tools/tree/master/forward_linker) for his useful script that inspired this one. 135 | -------------------------------------------------------------------------------- /alias_creator.py: -------------------------------------------------------------------------------- 1 | """ 2 | Alias file creator for Obsidian vault. 3 | 4 | INPUT1: Path to vault 5 | INPUT2: Alias search key/string 6 | INPUT3: Filename of saved YAML file 7 | INPUT4: Number of lines to limit search from top of note file (enter 0 or "" for all) 8 | """ 9 | import os, sys 10 | from datetime import datetime 11 | import yaml 12 | 13 | 14 | def main(): 15 | # Use the inputs from the CLI or BAT file 16 | if len(sys.argv) > 1: 17 | search_path = sys.argv[1] # Location of the Vault folder 18 | search_str = sys.argv[2] # Alias indicator key to search for at start of line 19 | save_filename = sys.argv[3] # Filename of the YAML file 20 | line_limit = sys.argv[4] # Limit search of key to only top 'n' lines for speed 21 | else: 22 | # Ask the user to enter string to search 23 | search_path = input("Enter directory path to search : ") 24 | search_str = input("Enter the search string : ") 25 | save_filename = input("Enter the filename of the YAML file : ") 26 | line_limit = input("Enter how many lines to limit search to : ") 27 | 28 | # Set blank line_limit as zero (infinite lines) if blank 29 | if not line_limit: 30 | line_limit = 0 31 | else: # set type as an int value 32 | line_limit = int(line_limit) 33 | 34 | # Collect all markdown files within the vault 35 | filepaths = [] 36 | file_extn = '.md' 37 | for root, dirs, files in os.walk(search_path): 38 | for file in files: 39 | if file.endswith(file_extn): 40 | filepaths.append(os.path.join(root,file)) 41 | 42 | # Store the Filenames and the Aliases in a Dictionary list 43 | dict_file = [] 44 | # Repeat for each file in the directory 45 | for fpath in filepaths: 46 | # Open file for reading 47 | fo = open(fpath) 48 | # Read the first line from the file 49 | line = fo.readline() 50 | # Initialize counter for line number 51 | line_no = 1 52 | # Boolean to check limit condition 53 | limit = False 54 | 55 | # Loop until EOF and while Line number is within limit range 56 | while (line != '') and (limit == False): 57 | # Search for string in line 58 | index = line.find(search_str) 59 | # check for occurrence at the start of line only 60 | if (index == 0): 61 | # Remove the search string from the line and split into list if multiple 62 | line = line.replace(search_str,"").split(",") 63 | # Remove all leading and trailing whitespaces 64 | line = [x.rstrip() for x in line] 65 | line = [x.lstrip() for x in line] 66 | 67 | # Get filename without extension 68 | fname = os.path.split(fpath)[1].split('.')[0] 69 | # Append the filename and aliases to the dictionary list 70 | dict_file.append({fname:line}) 71 | 72 | # Read next line 73 | line = fo.readline() 74 | # Increment line counter 75 | line_no += 1 76 | # Check whether we've reached the line_limit if one is set 77 | if (line_no > line_limit) and (line_limit != 0): 78 | limit = True 79 | # Close the files 80 | fo.close() 81 | 82 | # Construct the header for the Alias file 83 | title = f"# {'-'*30}\n# ALIAS FILE FOR OBSIDIAN VAULT" 84 | vault = f"# Vault: {os.path.split(search_path)[1]}" 85 | create = f"# Created: {datetime.now().strftime('%d-%m-%Y, %H:%M:%S')}" 86 | inputs = f"# Alias Key: '{search_str}'\n# Line Limit: {line_limit} lines" 87 | header = f"{title}\n{vault}\n{create}\n# {'-'*30}\n{inputs}\n# {'-'*30}\n" 88 | 89 | 90 | # Save the dictionary list as a YAML file 91 | with open(save_filename+'.yml', 'w') as file: 92 | file.writelines(header+"\n") 93 | print(header) 94 | for d in dict_file: 95 | documents = yaml.dump(d, file) 96 | print(d) 97 | file.writelines("\n") 98 | 99 | 100 | 101 | if __name__ == "__main__": 102 | 103 | main() 104 | print(f"\n# {'-'*30}") 105 | 106 | --------------------------------------------------------------------------------