How to Strip Path Prefixes from find Command Output for Deployment Scripts


18 views

When automating file deployments using find commands, we often encounter path prefixes that interfere with our copy operations. Consider this common scenario:

find . -type f -mtime -14 > deploy.txt
# Output contains './path/to/file.ext' 
# But we need just 'path/to/file.ext'

Here are three effective approaches to remove the leading ./:

1. Using parameter expansion in a loop

find . -type f -mtime -14 | while read -r file; do
  echo "${file#./}" >> deploy.txt
done

2. Leveraging sed for direct stream editing

find . -type f -mtime -14 | sed 's|^\./||' > deploy.txt

3. Using printf formatting with find -print0

find . -type f -mtime -14 -printf '%P\\n' > deploy.txt

Here's how I integrated this into my production deployment workflow:

#!/bin/bash

# Generate clean file list
find . -type f -mtime -14 -printf '%P\\n' > /tmp/deploy.txt

# Deployment loop
BETA_DIR="/home/user/beta/public_html"
PROD_DIR="/home/user/public_html"

while read -r file; do
  if [[ -f "$BETA_DIR/$file" ]]; then
    cp -i "$BETA_DIR/$file" "$PROD_DIR/$file"
    echo "Deployed: $file"
  else
    echo "Warning: $file not found in beta" >&2
  fi
done < /tmp/deploy.txt

# Clean up
rm /tmp/deploy.txt

For more robust handling, consider these improvements:

# Skip directories accidentally captured
find . -type f -mtime -14 ! -path "./.*" -printf '%P\\n'

# Exclude specific directories
find . -type f -mtime -14 ! -path "./node_modules/*" -printf '%P\\n'

For large codebases, these optimizations help:

# Use parallel processing with xargs
find . -type f -mtime -14 -print0 | sed -z 's|^\./||' | xargs -0 -P4 -I{} cp -i "$BETA_DIR/{}" "$PROD_DIR/{}"

When automating file deployments between environments, we often need to process find command output that includes relative paths (./ prefix). Here's how to clean this up for reliable script execution.

For processing find output, we have several effective approaches:

# Using basename in a while loop
find . -type f -mtime -14 | while read -r file; do
  echo "$(basename "$file")"
done > deploy.txt

# Using parameter expansion (faster)
find . -type f -mtime -14 | while read -r file; do
  echo "${file##*/}"
done > deploy.txt

Here's a robust implementation that handles filenames with spaces and special characters:

#!/bin/bash
# Generate clean file list
find . -type f -mtime -14 -print0 | while IFS= read -r -d '' file; do
  echo "${file#*/}"
done > deploy.txt

# Deployment loop
while IFS= read -r -d '' file; do
  cp -iv "/home/user/beta/public_html/${file}" "/home/user/public_html/${file}"
done < <(find . -type f -mtime -14 -print0 | sed 's|^\./||')

For complex deployments, consider these enhancements:

# Exclude certain directories
find . -type f -mtime -14 ! -path "./cache/*" ! -path "./tmp/*" | sed 's|^\./||'

# Add timestamp logging
find . -type f -mtime -14 -printf "%TY-%Tm-%Td %TH:%TM %p\n" | awk '{sub(/^\.\//, ""); print}'

For better performance with large file sets:

find . -type f -mtime -14 -print0 | sed -z 's|^\./||' | xargs -0 -I {} cp -iv \
  "/home/user/beta/public_html/{}" "/home/user/public_html/{}"