#!/bin/csh -f # make_AllSigns # ------------------------------------------------------------------------- # Shell script to create symlinks in the folder # ~/fred/website/bristle/Tips/DontBeATrump/TrumpProtestRallies/AllSigns # to all image files in all sibling folders that have names starting with # "20" (all recent years). Also to all TXT files in such sibling folders # that match an image filename. With options to skip selected sibling # folders and selected files in sibling folders. Can then run makealbum # to get a single album and slideshow of all rally images. # # Notes: # # 1. A filename ending in .SKIP causes the same filename without .SKIP to # NOT be created as a symlink. And to be deleted if it already exists # as a symlink. For example, the existence of the file: # - file1.jpg.SKIP # blocks the creation of symlink: # - file1.jpg # It also causes the deletion of any existing symlink by that name. # Similarly, the existence of the file: # - file1.txt.SKIP # blocks the creation of symlink: # - file1.txt # It also causes the deletion of any existing symlink by that name. # # 2. SKIP files have the same effect on same-named TXT symlinks. Thus, # the existence of any of the files: # - file1.jpg.SKIP # - file1.gif.SKIP # - file1.png.SKIP # - file1.txt.SKIP # - file1.anything.SKIP # also blocks the creation of symlink: # - file1.txt # And causes the deletion of any existing symlink by that name. # This is because TXT files are assumed to be captions for same-named # image files, and are useless if the image is skipped. # The same is NOT true in reverse. A SKIP for a TXT file does NOT # block the creation, or cause the deletion, of any non-TXT symlinks. # # 3. SKIP files can also be used to block entire folders. The existence # of the file: # - folder1.SKIP # blocks the creation of any symlink that would have targeted a file # in the sibling folder: # - ../folder1 # For example: # - file1.txt -> ../folder1/file1.txt # - file1.jpg -> ../folder1/file1.jpg # - etc... # It also causes the deletion of any such existing symlinks. # # 4. Once you've blocked an entire sibling folder via .SKIP, you can # still unblock selected files. Create a special sibling folder # with a name like: # - ../2025_NoFaces # In that folder, put symlinks to the selected image and TXT files. # This script sees the symlinks in that folder because it's a sibling # folder with a name starting with "20". It creates symlinks to # those symlinks, just as it creates symlinks to normal image and TXT # files. When you publish that folder to the web server, the symlinks # are copied to the server, so the double indirection works fine when # the web server accesses the links to the images. It also works fine # locally when TXT files are copied by makealbum into slides and into # the main album page. As usual, the order of the thumbnails in the # album page and the order of the slides in the slideshow are the # alphabetic order of the names as seen by makealbum. So choose the # names of the symlinks carefully to fine-tune that order. Since the # names of my images and TXT files mostly start with a timestamp, and # since I use the same name for the link and target, these selected # files that bypass the .SKIP block appear in the same timeline as # all of my non-blocked files. # # 5. SKIP files can be separate files whose contents are entirely ignored, # as described above. Or they can be symlinks. For example, instead # of creating additional files with names ending in SKIP, as shown # above, you can rename the associated symlinks: # - file1.txt -> ../folder1/file1.txt # - file1.jpg -> ../folder1/file1.jpg # to have .SKIP extensions: # - file1.txt.SKIP -> ../folder1/file1.txt # - file1.jpg.SKIP -> ../folder1/file1.jpg # This has the exact same effect. The existence of the SKIP symlinks # prevents new symlinks from being created, and causes any old ones # to be deleted. # It also has the convenient side effect, even before you rerun this # script, of preventing them from being noticed by makealbum. Because # they no longer end in .txt or an image extension like .jpg, .gif, # .png, etc. So the next time makealbum runs, it doesn't add them to # the album/slideshow, and it removes them from any existing one. # So, which is the best practice? It depends: # - Pros of renaming the symlink # - Preserves the info about which sibling folder it was linked to. # If you ever want to reverse your SKIP decision, you can just # remove the .SKIP from the end of the symlink name. # If you had instead created a separate SKIP file, you could still # delete it later and rerun this script to reverse your SKIP # decision. But if there were multiple sibling folders containing # the same image filename, it might create a symlink to a different # image than last time. # - It is slightly easier in a tool like Mac Finder or Windows # Explorer to add .SKIP to the end of a long complex symlink name # than to create a new file with an identical name plus the .SKIP # extension. # - I prefer this approach # - Pros of creating a separate SKIP file # - Causes the symlink to be deleted, so there's less visual clutter # in a directory listing. # - In the scenario described above of reversing your SKIP decision # by removing the .SKIP from the end of the symlink name, if there # were multiple sibling folders containing the same image filename, # there's a chance of ending up with mismatched image and caption. # You might have added .SKIP to the image symlink name and not to # the TXT symlink name. Next time you ran this script, it would have # deleted the TXT symlink since the image was being skipped. When # you later remove the .SKIP from the image symlink name and rerun # this script, the image symlink still exists, so it doesn't get # changed or re-created. But the TXT symlink does not exist, so it # gets created if a TXT file exists in a sibling folder. But it # it might get created as a symlink to the caption (TXT file) for a # different image (same name in a different sibling folder) than the # image symlink refers to. Only matters if you have the same image # name in different sibling folders and some intentionally have no # caption, or a different caption. To avoid this problem, add .SKIP # to the names of both image and TXT symlinks. I don't usually # bother since any duplicate image names of mine have the same # caption. # # 6. This script has absolutely NO effect except to create/delete # symlinks in the AllSigns folder. It never creates anything other # than a symlink, never deletes anything other than a symlink, never # replaces a non-symlink file with a symlink, and never makes any # changes outside of the AllSigns folder. # # 7. This script is idempotent, meaning that it is safe to run multiple # times, to abort and rerun, etc. It cleans up after itself each time, # deleting previously created links as necessary, and creating any new # symlinks that are required. You can safely make any changes to the # target sibling folders, adding/deleting/editing image files and # captions. Then rerun this script, and it does the right things. # # 8. The makealbum script is also idempotent and cleans up after itself. # So, after making any such changes and rerunning this script, you # can rerun makealbum and it does the right things. Creates a clean # new album and slideshow, deletes obsolete slides, thumbnails, etc. # Both locally and on the web server. Totally self-healing. Edit # fearlessly! # # Weaknesses: # - If there are multiple sibling folders containing the same image name, # you'll get a symlink to one of them, but it might not be the one you # prefer. If so, delete the symlink manually and create a new one. # I include timestamps in the names of most of my images, so this is # a rare occurrence of me. If I DO have the same image name in multiple # folders, it's probably the same image, or even a symlink from one # image file to another, so it doesn't matter which one is symlinked # from AllSigns. # # ------------------------------------------------------------------------- # Revision History: # $Log$ # ------------------------------------------------------------------------- # Collect command line options while ($#argv > 0) if ("$1" == "-h" || "$1" == "--help") then echo "Usage: $0:t [options]" echo "Options:" echo " -h = Show this help text" echo " --help = Show this help text" exit 1 else if ("-" == "`echo $1:q | cut -c 1`") then echo "Error: Invalid option: $1:q" $0 --help exit 1 else # Not a recognized option. Assume it's the first argument break endif end # Collect command line arguments if ($#argv > 0) then echo "Error: Too many arguments" $0 --help exit 1 endif # Move to the links folder and loop through all sibling folders that start # with 20 (all recent years) in alphabetic order, creating symlinks to all # image and TXT files in the sibling folder. set links_dir = \ ~/fred/website/bristle/Tips/DontBeATrump/TrumpProtestRallies/AllSigns cd $links_dir set pushdsilent # Note: Double quotes outside the backticks cause the list of # folders, one per line, generated by find, to be quoted # so that embedded whitespace and special chars are tolerated. # The foreach command operates on each line as a folder name, # not each word of each line. # Note: The option -type d selects only directories, not symlinks. # Note: Do NOT enclose this path in quotes. That suppresses tilde expansion. foreach target_dir ("`find .. -maxdepth 1 -type d -name 20\* -print | sort`") if (-e "${target_dir:t}.SKIP") then echo "Skipping: $target_dir ..." continue endif pushd $target_dir echo "Processing: $target_dir ..." # Note: Loop over all image files in the target folder, but not also # all TXT files in the target folder. We only want to process # TXT files that match the name of an image file. Not any other # TXT files that may exist in the target folder. foreach image_file (*.[jJ][pP][gG] *.[gG][iI][fF] *.[pP][nN][gG]) set txt_file = "${image_file:r}.txt" pushd "$links_dir" # No need to test for existence of target image file. We found # it in the foreach loop specifier above. # Process the target image file. if (-e "$image_file.SKIP") then echo "Skipping image file: $image_file ..." continue # Note: Using -e here is OK because we already know the target image # file exists, so this is really a test for the existence of # the link. Would also detect the existence of a non-link # image file and leave it alone. # Using -l instead would not detect the existence of a # non-link image file and would replace it with a link. It # is possible that there's a real image file here. This # is a way for an image in AllSigns to override the image # in the target folder. Don't delete it. else if (-e "$image_file") then # echo "Image file or link exists: $image_file ..." else echo "Creating image link: $image_file ..." ln -s -i -v "$target_dir/$image_file" "$image_file" endif # Test for existence of target TXT file. There may not be one for # this image file. if (! -e "$target_dir/$txt_file") then continue endif # Process the target TXT file if (-e "$txt_file.SKIP") then echo "Skipping TXT file: $txt_file ..." # Note: Using -e here is OK because we already know the target TXT # file exists, so this is really a test for the existence of # the link. Would also detect the existence of a non-link # TXT file and leave it alone. # Using -l instead would not detect the existence of a # non-link TXT file and would replace it with a link. It # is possible that there's a real TXT file here. This # is a way for a caption in AllSigns to override the caption # in the target folder. Don't delete it. else if (-e "$txt_file") then # echo "TXT file or link exists: $txt_file ..." else echo "Creating TXT link: $txt_file ..." ln -s -i -v "$target_dir/$txt_file" "$txt_file" endif popd end popd end # Delete links flagged with SKIP, and their associated TXT links if (`find . -maxdepth 1 -name "*.SKIP" -print` != "") then foreach skip_flag_file (*.SKIP) set skipped_file = "$skip_flag_file:r" if (-l "$skipped_file") then echo "Deleting skipped link: $skipped_file ..." rmlink -i -v $skipped_file:q endif set txt_file = "${skipped_file:r}.txt" if (-l "$txt_file") then echo "Deleting associated TXT link: $txt_file ..." rmlink -i -v $txt_file:q endif # Delete links into folders flagged with SKIP foreach file (*) if (-l "$file") then set link_target = "`readlink $file:q`" # Note: :h discards filename, leaving only path to file if ("$link_target:h" == "../$skipped_file") then echo "Deleting link into skipped folder: $file -> $link_target ..." rmlink -i -v $file:q endif endif end end endif # Delete all image links that have a non-existent target, and their # corresponding TXT links also cd $links_dir if (`find . -maxdepth 1 \ -iname "*.jpg" \ -or -iname "*.gif" \ -or -iname "*.png" \ -print` \ != "" \ ) then foreach image_file (*.[jJ][pP][gG] *.[gG][iI][fF] *.[pP][nN][gG]) # Note: We know the image file or link exists since the foreach loop # found it. Use -e to test for the existence of the target # image file. if (! -e "$image_file") then echo "Deleting dead image link: $image_file ..." rmlink -i -v $image_file:q # Also delete any previously created TXT link. A caption is # useless without an image. # Note: Use -l here, not -e which would test for the existence # of the target file of the link, not just the link itself. # If the target file doesn't exist, we still want to delete # the link. # Also, -e would test for the existence of a non-link # TXT file, and delete it, which we don't want. The non-link # caption will be ignored by makealbum since there's no image # for it, but we want to delete ONLY links here. Non-link # captions must have been created manually, and may still be # wanted. set txt_file = "${image_file:r}.txt" if (-l "$txt_file") then echo "Deleting dead image's TXT link: $txt_file ..." rmlink -i -v $txt_file:q endif endif end # Delete all TXT links that have a non-existent target. if (`find . -maxdepth 1 -name "*.txt" -print` != "") then foreach txt_file (*.txt) # Note: We know the TXT file or link exists since the foreach loop # found it. Use -e to test for the existence of the target # TXT file. if (! -e "$txt_file") then echo "Deleting dead TXT link: $txt_file ..." rmlink -i -v $txt_file:q endif end endif